+ + Редактор Баннеров +
+Создание и редактирование баннеров для сайта
+diff --git a/.history/.env_20251019201239 b/.history/.env_20251019201239 new file mode 100644 index 0000000..bbf9a40 --- /dev/null +++ b/.history/.env_20251019201239 @@ -0,0 +1,34 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database +MONGODB_URI=mongodb://localhost:27017/smartsoltech + +# JWT Secret +JWT_SECRET=your_super_secret_jwt_key_here_change_in_production + +# Session Secret +SESSION_SECRET=your_session_secret_here_change_in_production + +# Telegram Bot +TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here +TELEGRAM_CHAT_ID=your_telegram_chat_id_here + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=your_email@gmail.com +EMAIL_PASS=your_email_password + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.env_20251019201325 b/.history/.env_20251019201325 new file mode 100644 index 0000000..71be5b1 --- /dev/null +++ b/.history/.env_20251019201325 @@ -0,0 +1,34 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database +MONGODB_URI=mongodb://localhost:27017/smartsoltech + +# JWT Secret +JWT_SECRET=:AISDFUhbsLKFJADESFIOlugtywow8fryuelhbf2p349[yresdugiflhbjKASDJfbh + +# Session Secret +SESSION_SECRET=LKSJ:DFHGAJKLfbads;oflIAFK:DHJSUGBVdil;asufgtdshjfv + +# Telegram Bot +TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here +TELEGRAM_CHAT_ID=your_telegram_chat_id_here + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=your_email@gmail.com +EMAIL_PASS=your_email_password + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.env_20251019201339 b/.history/.env_20251019201339 new file mode 100644 index 0000000..d0b7103 --- /dev/null +++ b/.history/.env_20251019201339 @@ -0,0 +1,34 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database +MONGODB_URI=mongodb://localhost:27017/smartsoltech + +# JWT Secret +JWT_SECRET=:AISDFUhbsLKFJADESFIOlugtywow8fryuelhbf2p349[yresdugiflhbjKASDJfbh + +# Session Secret +SESSION_SECRET=LKSJ:DFHGAJKLfbads;oflIAFK:DHJSUGBVdil;asufgtdshjfv + +# Telegram Bot +TELEGRAM_BOT_TOKEN=8289431590:AAEVZWjb6PgGbv-jivphXfqCMD9c6NqE870 +TELEGRAM_CHAT_ID=your_telegram_chat_id_here + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=your_email@gmail.com +EMAIL_PASS=your_email_password + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.env_20251019201413 b/.history/.env_20251019201413 new file mode 100644 index 0000000..2387270 --- /dev/null +++ b/.history/.env_20251019201413 @@ -0,0 +1,34 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database +MONGODB_URI=mongodb://localhost:27017/smartsoltech + +# JWT Secret +JWT_SECRET=:AISDFUhbsLKFJADESFIOlugtywow8fryuelhbf2p349[yresdugiflhbjKASDJfbh + +# Session Secret +SESSION_SECRET=LKSJ:DFHGAJKLfbads;oflIAFK:DHJSUGBVdil;asufgtdshjfv + +# Telegram Bot +TELEGRAM_BOT_TOKEN=8289431590:AAEVZWjb6PgGbv-jivphXfqCMD9c6NqE870 +TELEGRAM_CHAT_ID=-4949859416 + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=your_email@gmail.com +EMAIL_PASS=your_email_password + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.env_20251019201552 b/.history/.env_20251019201552 new file mode 100644 index 0000000..5f88f82 --- /dev/null +++ b/.history/.env_20251019201552 @@ -0,0 +1,39 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database - PostgreSQL +DATABASE_URL=postgresql://postgres:password@localhost:5432/smartsoltech +DB_HOST=localhost +DB_PORT=5432 +DB_NAME=smartsoltech +DB_USER=postgres +DB_PASSWORD=password + +# JWT Secret +JWT_SECRET=:AISDFUhbsLKFJADESFIOlugtywow8fryuelhbf2p349[yresdugiflhbjKASDJfbh + +# Session Secret +SESSION_SECRET=LKSJ:DFHGAJKLfbads;oflIAFK:DHJSUGBVdil;asufgtdshjfv + +# Telegram Bot +TELEGRAM_BOT_TOKEN=8289431590:AAEVZWjb6PgGbv-jivphXfqCMD9c6NqE870 +TELEGRAM_CHAT_ID=-4949859416 + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=your_email@gmail.com +EMAIL_PASS=your_email_password + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.env_20251019201634 b/.history/.env_20251019201634 new file mode 100644 index 0000000..036433e --- /dev/null +++ b/.history/.env_20251019201634 @@ -0,0 +1,39 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database - PostgreSQL +DATABASE_URL=postgresql://trevor:R0sebud@localhost:5432/smartsoltech +DB_HOST=localhost +DB_PORT=5432 +DB_NAME=smartsoltech +DB_USER=trevor +DB_PASSWORD=R0sebud + +# JWT Secret +JWT_SECRET=:AISDFUhbsLKFJADESFIOlugtywow8fryuelhbf2p349[yresdugiflhbjKASDJfbh + +# Session Secret +SESSION_SECRET=LKSJ:DFHGAJKLfbads;oflIAFK:DHJSUGBVdil;asufgtdshjfv + +# Telegram Bot +TELEGRAM_BOT_TOKEN=8289431590:AAEVZWjb6PgGbv-jivphXfqCMD9c6NqE870 +TELEGRAM_CHAT_ID=-4949859416 + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=your_email@gmail.com +EMAIL_PASS=your_email_password + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.env_20251021214349 b/.history/.env_20251021214349 new file mode 100644 index 0000000..6cf440b --- /dev/null +++ b/.history/.env_20251021214349 @@ -0,0 +1,39 @@ +# Environment Configuration +NODE_ENV=development +PORT=3000 + +# Database - PostgreSQL +DATABASE_URL=postgresql://trevor:R0sebud@localhost:5432/smartsoltech +DB_HOST=localhost +DB_PORT=5432 +DB_NAME=smartsoltech +DB_USER=trevor +DB_PASSWORD=R0sebud + +# JWT Secret +JWT_SECRET=:AISDFUhbsLKFJADESFIOlugtywow8fryuelhbf2p349[yresdugiflhbjKASDJfbh + +# Session Secret +SESSION_SECRET=LKSJ:DFHGAJKLfbads;oflIAFK:DHJSUGBVdil;asufgtdshjfv + +# Telegram Bot +TELEGRAM_BOT_TOKEN=8289431590:AAEVZWjb6PgGbv-jivphXfqCMD9c6NqE870 +TELEGRAM_CHAT_ID=-4949859416 + +# Email Configuration (for contact forms) +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USER=tsoy4uk@gmail.com +EMAIL_PASS=Cl0ud_1985_! + +# Admin Credentials (default) +ADMIN_EMAIL=admin@smartsoltech.kr +ADMIN_PASSWORD=admin123456 + +# File Upload +MAX_FILE_SIZE=10485760 +UPLOAD_PATH=./public/uploads + +# Site Configuration +SITE_URL=https://smartsoltech.kr +SITE_NAME=SmartSolTech \ No newline at end of file diff --git a/.history/.github/copilot-instructions_20251019201336.md b/.history/.github/copilot-instructions_20251019201336.md new file mode 100644 index 0000000..c35af6b --- /dev/null +++ b/.history/.github/copilot-instructions_20251019201336.md @@ -0,0 +1,151 @@ +# SmartSolTech Website - AI Coding Agent Instructions + +## Project Overview +SmartSolTech is a **Korean tech services company** PWA with an admin panel, portfolio management, Telegram integration, and service calculator. Built with Node.js/Express backend, EJS templating, MongoDB, and modern PWA features. + +## Architecture & Key Patterns + +### 🏗️ Backend Architecture +- **Main server**: `server.js` - Express app with comprehensive middleware stack +- **Models**: MongoDB with Mongoose ODM - all in `/models/` (User, Portfolio, Service, Contact, SiteSettings) +- **Routes**: RESTful API patterns in `/routes/` - separate files per domain +- **Authentication**: Dual auth system - JWT tokens for API, sessions for web pages +- **Validation**: express-validator middleware in `/middleware/validation.js` with Korean error messages + +### 🔑 Authentication Pattern +```javascript +// Two authentication strategies: +// 1. JWT for API endpoints (authenticateToken) +// 2. Session-based for web pages (authenticateSession) +// See middleware/auth.js for implementations +``` + +### 📊 Data Models Key Features +- **Portfolio**: Has virtual `primaryImage` getter, text search indexes, and SEO fields +- **Service**: Complex pricing structure with features array (included/not included) +- **User**: bcrypt password hashing with pre-save hook and comparePassword method +- **All models**: Use timestamps and have soft-delete patterns where applicable + +### 🛣️ Route Organization +- **Admin routes** (`/admin`): Session-based auth, server-side rendered EJS views +- **API routes** (`/api/*`): JWT auth, JSON responses, rate-limited +- **Public routes** (`/`): Mixed auth (optional), EJS templates with PWA support + +## Development Workflow + +### 🚀 Essential Commands +```bash +# Development with hot reload and file watching +npm run dev + +# Initialize database with admin user and sample data +npm run init-db + +# Production build with webpack optimization +npm run build + +# Database setup creates: +# - Admin user (from .env: ADMIN_EMAIL/ADMIN_PASSWORD) +# - Sample services, portfolio items, site settings +``` + +### 🔧 Environment Setup +**Critical `.env` variables**: +- `MONGODB_URI` - Database connection +- `SESSION_SECRET`, `JWT_SECRET` - Security keys +- `ADMIN_EMAIL`, `ADMIN_PASSWORD` - Initial admin account +- `TELEGRAM_BOT_TOKEN` - Optional Telegram integration +- `NODE_ENV` - Controls error verbosity and security settings + +## Frontend Architecture + +### 🎨 View Layer (EJS Templates) +- **Layout system**: `views/layout.ejs` is main wrapper +- **Partials**: `views/partials/` for reusable components (navigation, footer) +- **Admin panel**: Separate layout `admin/layout.ejs` with different styling +- **Internationalization**: Content in Korean, supports locales in `/locales/` + +### 📱 PWA Implementation +- **Service Worker**: `public/sw.js` - caches static files, dynamic routes, and API responses +- **Manifest**: `public/manifest.json` - app metadata and icons +- **Offline-first**: Service worker handles network failures gracefully +- **Cache strategy**: Static files cached immediately, dynamic content cached on demand + +### 🎯 Frontend JavaScript Patterns +- **Main script**: `public/js/main.js` - handles navigation, scroll effects, form interactions +- **Calculator**: `public/js/calculator.js` - complex service pricing calculations +- **Libraries**: AOS animations, Tailwind CSS, Socket.io for real-time features + +## Key Integration Points + +### 📧 Communication Systems +- **Telegram Bot**: Optional integration for admin notifications (contact forms, orders) +- **Email**: Nodemailer for SMTP email sending (contact forms, notifications) +- **Real-time**: Socket.io setup for live updates (dashboard, notifications) + +### 🔒 Security Patterns +- **Helmet**: CSP headers allowing specific domains (fonts.googleapis.com, cdnjs.cloudflare.com) +- **Rate limiting**: Applied to `/api/*` routes (100 requests/15min per IP) +- **Input validation**: Korean-language error messages, comprehensive field validation +- **File uploads**: Multer with Sharp image processing, stored in `public/uploads/` + +### 🗄️ Database Patterns +- **Connection**: Single MongoDB connection with connection pooling +- **Indexing**: Text search on Portfolio, compound indexes for performance +- **Session storage**: MongoDB session store for persistence + +## Business Logic Specifics + +### 💰 Service Calculator +- **Complex pricing**: Base price + features + timeline modifiers +- **Multi-step form**: Service selection → customization → contact info → quote +- **Integration**: Calculator data feeds into Contact model for lead tracking + +### 🎨 Portfolio Management +- **Image handling**: Multiple images per project, primary image logic +- **Categories**: Predefined categories (web-development, mobile-app, ui-ux-design, etc.) +- **SEO optimization**: Meta fields, structured data for portfolio items + +### 👑 Admin Panel Features +- **Dashboard**: Statistics, recent activity, quick actions +- **Content management**: CRUD for Portfolio, Services, Site Settings +- **Media gallery**: File upload with image optimization +- **Contact management**: Lead tracking, status updates, response handling + +## Common Tasks & Patterns + +### 🔧 Adding New Features +1. **Model**: Create in `/models/` with proper validation and indexes +2. **Routes**: Add to `/routes/` with appropriate auth middleware +3. **Views**: EJS templates in `/views/` using layout system +4. **API**: JSON endpoints with validation middleware +5. **Frontend**: Add to `public/js/` with proper event handling + +### 🐛 Debugging Workflow +- **Development**: Use `npm run dev` for auto-restart and detailed logging +- **Database**: Check MongoDB connection and sample data with `npm run init-db` +- **Authentication**: Test both JWT (API) and session (web) auth flows +- **PWA**: Check service worker registration and cache behavior in dev tools + +### 📦 Deployment Considerations +- **Environment**: Production requires secure cookies, CSP, and rate limiting +- **Database**: Ensure MongoDB indexes are created for performance +- **Assets**: Static files served by Express, consider CDN for production +- **Monitoring**: Error handling sends different messages based on NODE_ENV + +## File Structure Quick Reference +``` +├── models/ # MongoDB schemas with business logic +├── routes/ # Express routes (API + web pages) +├── middleware/ # Auth, validation, error handling +├── views/ # EJS templates with Korean content +├── public/ # Static assets + PWA files +├── scripts/ # Database init, dev server, build tools +└── server.js # Main Express application +``` + +## Korean Language Notes +- **UI Text**: All user-facing content in Korean +- **Error Messages**: Validation errors in Korean (`middleware/validation.js`) +- **Admin Interface**: Korean labels and messages throughout admin panel +- **SEO Content**: Korean meta descriptions and structured data \ No newline at end of file diff --git a/.history/.github/copilot-instructions_20251019201424.md b/.history/.github/copilot-instructions_20251019201424.md new file mode 100644 index 0000000..c35af6b --- /dev/null +++ b/.history/.github/copilot-instructions_20251019201424.md @@ -0,0 +1,151 @@ +# SmartSolTech Website - AI Coding Agent Instructions + +## Project Overview +SmartSolTech is a **Korean tech services company** PWA with an admin panel, portfolio management, Telegram integration, and service calculator. Built with Node.js/Express backend, EJS templating, MongoDB, and modern PWA features. + +## Architecture & Key Patterns + +### 🏗️ Backend Architecture +- **Main server**: `server.js` - Express app with comprehensive middleware stack +- **Models**: MongoDB with Mongoose ODM - all in `/models/` (User, Portfolio, Service, Contact, SiteSettings) +- **Routes**: RESTful API patterns in `/routes/` - separate files per domain +- **Authentication**: Dual auth system - JWT tokens for API, sessions for web pages +- **Validation**: express-validator middleware in `/middleware/validation.js` with Korean error messages + +### 🔑 Authentication Pattern +```javascript +// Two authentication strategies: +// 1. JWT for API endpoints (authenticateToken) +// 2. Session-based for web pages (authenticateSession) +// See middleware/auth.js for implementations +``` + +### 📊 Data Models Key Features +- **Portfolio**: Has virtual `primaryImage` getter, text search indexes, and SEO fields +- **Service**: Complex pricing structure with features array (included/not included) +- **User**: bcrypt password hashing with pre-save hook and comparePassword method +- **All models**: Use timestamps and have soft-delete patterns where applicable + +### 🛣️ Route Organization +- **Admin routes** (`/admin`): Session-based auth, server-side rendered EJS views +- **API routes** (`/api/*`): JWT auth, JSON responses, rate-limited +- **Public routes** (`/`): Mixed auth (optional), EJS templates with PWA support + +## Development Workflow + +### 🚀 Essential Commands +```bash +# Development with hot reload and file watching +npm run dev + +# Initialize database with admin user and sample data +npm run init-db + +# Production build with webpack optimization +npm run build + +# Database setup creates: +# - Admin user (from .env: ADMIN_EMAIL/ADMIN_PASSWORD) +# - Sample services, portfolio items, site settings +``` + +### 🔧 Environment Setup +**Critical `.env` variables**: +- `MONGODB_URI` - Database connection +- `SESSION_SECRET`, `JWT_SECRET` - Security keys +- `ADMIN_EMAIL`, `ADMIN_PASSWORD` - Initial admin account +- `TELEGRAM_BOT_TOKEN` - Optional Telegram integration +- `NODE_ENV` - Controls error verbosity and security settings + +## Frontend Architecture + +### 🎨 View Layer (EJS Templates) +- **Layout system**: `views/layout.ejs` is main wrapper +- **Partials**: `views/partials/` for reusable components (navigation, footer) +- **Admin panel**: Separate layout `admin/layout.ejs` with different styling +- **Internationalization**: Content in Korean, supports locales in `/locales/` + +### 📱 PWA Implementation +- **Service Worker**: `public/sw.js` - caches static files, dynamic routes, and API responses +- **Manifest**: `public/manifest.json` - app metadata and icons +- **Offline-first**: Service worker handles network failures gracefully +- **Cache strategy**: Static files cached immediately, dynamic content cached on demand + +### 🎯 Frontend JavaScript Patterns +- **Main script**: `public/js/main.js` - handles navigation, scroll effects, form interactions +- **Calculator**: `public/js/calculator.js` - complex service pricing calculations +- **Libraries**: AOS animations, Tailwind CSS, Socket.io for real-time features + +## Key Integration Points + +### 📧 Communication Systems +- **Telegram Bot**: Optional integration for admin notifications (contact forms, orders) +- **Email**: Nodemailer for SMTP email sending (contact forms, notifications) +- **Real-time**: Socket.io setup for live updates (dashboard, notifications) + +### 🔒 Security Patterns +- **Helmet**: CSP headers allowing specific domains (fonts.googleapis.com, cdnjs.cloudflare.com) +- **Rate limiting**: Applied to `/api/*` routes (100 requests/15min per IP) +- **Input validation**: Korean-language error messages, comprehensive field validation +- **File uploads**: Multer with Sharp image processing, stored in `public/uploads/` + +### 🗄️ Database Patterns +- **Connection**: Single MongoDB connection with connection pooling +- **Indexing**: Text search on Portfolio, compound indexes for performance +- **Session storage**: MongoDB session store for persistence + +## Business Logic Specifics + +### 💰 Service Calculator +- **Complex pricing**: Base price + features + timeline modifiers +- **Multi-step form**: Service selection → customization → contact info → quote +- **Integration**: Calculator data feeds into Contact model for lead tracking + +### 🎨 Portfolio Management +- **Image handling**: Multiple images per project, primary image logic +- **Categories**: Predefined categories (web-development, mobile-app, ui-ux-design, etc.) +- **SEO optimization**: Meta fields, structured data for portfolio items + +### 👑 Admin Panel Features +- **Dashboard**: Statistics, recent activity, quick actions +- **Content management**: CRUD for Portfolio, Services, Site Settings +- **Media gallery**: File upload with image optimization +- **Contact management**: Lead tracking, status updates, response handling + +## Common Tasks & Patterns + +### 🔧 Adding New Features +1. **Model**: Create in `/models/` with proper validation and indexes +2. **Routes**: Add to `/routes/` with appropriate auth middleware +3. **Views**: EJS templates in `/views/` using layout system +4. **API**: JSON endpoints with validation middleware +5. **Frontend**: Add to `public/js/` with proper event handling + +### 🐛 Debugging Workflow +- **Development**: Use `npm run dev` for auto-restart and detailed logging +- **Database**: Check MongoDB connection and sample data with `npm run init-db` +- **Authentication**: Test both JWT (API) and session (web) auth flows +- **PWA**: Check service worker registration and cache behavior in dev tools + +### 📦 Deployment Considerations +- **Environment**: Production requires secure cookies, CSP, and rate limiting +- **Database**: Ensure MongoDB indexes are created for performance +- **Assets**: Static files served by Express, consider CDN for production +- **Monitoring**: Error handling sends different messages based on NODE_ENV + +## File Structure Quick Reference +``` +├── models/ # MongoDB schemas with business logic +├── routes/ # Express routes (API + web pages) +├── middleware/ # Auth, validation, error handling +├── views/ # EJS templates with Korean content +├── public/ # Static assets + PWA files +├── scripts/ # Database init, dev server, build tools +└── server.js # Main Express application +``` + +## Korean Language Notes +- **UI Text**: All user-facing content in Korean +- **Error Messages**: Validation errors in Korean (`middleware/validation.js`) +- **Admin Interface**: Korean labels and messages throughout admin panel +- **SEO Content**: Korean meta descriptions and structured data \ No newline at end of file diff --git a/.history/REPORT_20251020225831.md b/.history/REPORT_20251020225831.md new file mode 100644 index 0000000..584e50e --- /dev/null +++ b/.history/REPORT_20251020225831.md @@ -0,0 +1,132 @@ +# 🎯 SmartSolTech - Отчет о Выполненных Исправлениях + +## 📋 Задачи которые были выполнены: + +### 1. 🏠 **Исправление главной страницы** +- ✅ **Проблема**: Стили на главной странице были поломаны +- ✅ **Решение**: + - Полностью переписан `base.css` с принудительными стилями (!important) + - Улучшен градиент hero-секции с многослойными эффектами + - Добавлены анимации и hover-эффекты для кнопок + - Исправлена навигация с backdrop-filter и webkit префиксами + - Оптимизирована отзывчивость для мобильных устройств + +### 2. 📐 **Компактные баннеры для внутренних страниц** +- ✅ **Проблема**: Hero-баннеры на всех страницах были полноэкранными +- ✅ **Решение**: + - Создан класс `.hero-section-compact` для внутренних страниц + - Уменьшена высота с 100vh до 40vh (50vh максимум) + - Обновлены страницы: "О нас", "Услуги" + - Сохранен полноэкранный баннер только на главной странице + +### 3. 🖼️ **Система редактирования изображений баннеров** + +#### **A. Backend API (/routes/media.js)** +- ✅ Загрузка одного изображения: `POST /media/upload` +- ✅ Загрузка нескольких изображений: `POST /media/upload-multiple` +- ✅ Удаление изображений: `DELETE /media/:filename` +- ✅ Список изображений: `GET /media/list` +- ✅ Автоматическая оптимизация изображений с Sharp +- ✅ Создание thumbnails (300x200, 800x600, 1200x900) +- ✅ Конвертация в WebP для лучшего сжатия +- ✅ Безопасность: аутентификация и валидация файлов + +#### **B. Frontend Редактор (/views/admin/banner-editor.ejs)** +- ✅ Интуитивный интерфейс с табами для разных страниц +- ✅ Drag & Drop загрузка изображений +- ✅ Превью изображений с возможностью удаления +- ✅ Индикатор прогресса загрузки +- ✅ Галерея загруженных изображений +- ✅ Мгновенная смена баннеров одним кликом +- ✅ Локальное сохранение настроек в localStorage + +#### **C. Интеграция с админкой** +- ✅ Новый маршрут: `/admin/banner-editor` +- ✅ Аутентификация через админ-сессии +- ✅ Интеграция с существующей админ панелью + +## 🔧 Технические улучшения: + +### **CSS архитектура:** +```css +base.css (16KB) - Принудительные стили и reset +main.css (11KB) - Компоненты и анимации + компактные баннеры +fixes.css (6KB) - Дополнительные исправления +``` + +### **Оптимизация изображений:** +- Автоматическое создание 4 размеров (thumbnail, medium, large, original) +- Конвертация в WebP (экономия до 50% размера) +- Максимальный размер файла: 10MB +- Поддержка: JPG, PNG, GIF, WebP + +### **Безопасность:** +- Валидация типов файлов +- Защита от path traversal атак +- Аутентификация для всех операций +- Автоматическая очистка при ошибках + +## 📊 Результаты тестирования: + +``` +🏠 ГЛАВНАЯ СТРАНИЦА: ✅ 200 OK (0.015s) +🎨 О НАС (компактный): ✅ 200 OK (0.007s) +🎨 УСЛУГИ (компактный): ✅ 200 OK (0.009s) +📱 ПОРТФОЛИО: ✅ 200 OK (0.012s) +🧮 КАЛЬКУЛЯТОР: ✅ 200 OK (0.008s) +📸 РЕДАКТОР БАННЕРОВ: ✅ 302 (требует авторизации) +🎨 CSS ФАЙЛЫ: ✅ Все загружаются корректно +📁 UPLOADS ПАПКА: ✅ Создана и готова +``` + +## 🚀 Как использовать редактор баннеров: + +### **Шаг 1: Доступ** +``` +URL: http://localhost:3000/admin/banner-editor +Требуется: Авторизация в админ панели +``` + +### **Шаг 2: Загрузка изображений** +1. Нажать "Загрузить Изображения" +2. Перетащить файлы или выбрать через кнопку +3. Посмотреть превью и нажать "Загрузить" +4. Система автоматически создаст оптимизированные версии + +### **Шаг 3: Установка баннера** +1. Выбрать страницу во вкладках (Главная, О нас, Услуги, Портфолио) +2. Нажать "Использовать" на нужном изображении +3. Баннер мгновенно обновится +4. Настройки сохраняются автоматически + +### **Шаг 4: Управление** +- Удаление: кнопка "Удалить" в галерее +- Обновление: кнопка "Обновить" +- Сброс к градиенту: кнопка "Удалить" на текущем баннере + +## 🎯 Итоговое состояние: + +### ✅ **Что работает:** +- Главная страница с исправленными стилями +- Компактные баннеры на внутренних страницах +- Полнофункциональный редактор изображений +- API для загрузки и управления медиа +- Автоматическая оптимизация изображений +- Безопасная система аутентификации + +### 🔄 **Готово к использованию:** +- Сервер: `http://localhost:3000` (PID: 24059) +- Админка: `http://localhost:3000/admin` +- Редактор: `http://localhost:3000/admin/banner-editor` +- Папка загрузок: `/public/uploads/` (готова к использованию) + +### 📈 **Преимущества реализации:** +1. **Производительность**: WebP формат + множественные размеры +2. **UX**: Drag & Drop + мгновенные превью +3. **Безопасность**: Полная валидация + аутентификация +4. **Масштабируемость**: Готова к добавлению новых страниц +5. **Мобильность**: Отзывчивый дизайн на всех устройствах + +--- + +**🎉 Все задачи выполнены успешно! Система готова к продуктивному использованию.** \ No newline at end of file diff --git a/.history/REPORT_20251020225845.md b/.history/REPORT_20251020225845.md new file mode 100644 index 0000000..584e50e --- /dev/null +++ b/.history/REPORT_20251020225845.md @@ -0,0 +1,132 @@ +# 🎯 SmartSolTech - Отчет о Выполненных Исправлениях + +## 📋 Задачи которые были выполнены: + +### 1. 🏠 **Исправление главной страницы** +- ✅ **Проблема**: Стили на главной странице были поломаны +- ✅ **Решение**: + - Полностью переписан `base.css` с принудительными стилями (!important) + - Улучшен градиент hero-секции с многослойными эффектами + - Добавлены анимации и hover-эффекты для кнопок + - Исправлена навигация с backdrop-filter и webkit префиксами + - Оптимизирована отзывчивость для мобильных устройств + +### 2. 📐 **Компактные баннеры для внутренних страниц** +- ✅ **Проблема**: Hero-баннеры на всех страницах были полноэкранными +- ✅ **Решение**: + - Создан класс `.hero-section-compact` для внутренних страниц + - Уменьшена высота с 100vh до 40vh (50vh максимум) + - Обновлены страницы: "О нас", "Услуги" + - Сохранен полноэкранный баннер только на главной странице + +### 3. 🖼️ **Система редактирования изображений баннеров** + +#### **A. Backend API (/routes/media.js)** +- ✅ Загрузка одного изображения: `POST /media/upload` +- ✅ Загрузка нескольких изображений: `POST /media/upload-multiple` +- ✅ Удаление изображений: `DELETE /media/:filename` +- ✅ Список изображений: `GET /media/list` +- ✅ Автоматическая оптимизация изображений с Sharp +- ✅ Создание thumbnails (300x200, 800x600, 1200x900) +- ✅ Конвертация в WebP для лучшего сжатия +- ✅ Безопасность: аутентификация и валидация файлов + +#### **B. Frontend Редактор (/views/admin/banner-editor.ejs)** +- ✅ Интуитивный интерфейс с табами для разных страниц +- ✅ Drag & Drop загрузка изображений +- ✅ Превью изображений с возможностью удаления +- ✅ Индикатор прогресса загрузки +- ✅ Галерея загруженных изображений +- ✅ Мгновенная смена баннеров одним кликом +- ✅ Локальное сохранение настроек в localStorage + +#### **C. Интеграция с админкой** +- ✅ Новый маршрут: `/admin/banner-editor` +- ✅ Аутентификация через админ-сессии +- ✅ Интеграция с существующей админ панелью + +## 🔧 Технические улучшения: + +### **CSS архитектура:** +```css +base.css (16KB) - Принудительные стили и reset +main.css (11KB) - Компоненты и анимации + компактные баннеры +fixes.css (6KB) - Дополнительные исправления +``` + +### **Оптимизация изображений:** +- Автоматическое создание 4 размеров (thumbnail, medium, large, original) +- Конвертация в WebP (экономия до 50% размера) +- Максимальный размер файла: 10MB +- Поддержка: JPG, PNG, GIF, WebP + +### **Безопасность:** +- Валидация типов файлов +- Защита от path traversal атак +- Аутентификация для всех операций +- Автоматическая очистка при ошибках + +## 📊 Результаты тестирования: + +``` +🏠 ГЛАВНАЯ СТРАНИЦА: ✅ 200 OK (0.015s) +🎨 О НАС (компактный): ✅ 200 OK (0.007s) +🎨 УСЛУГИ (компактный): ✅ 200 OK (0.009s) +📱 ПОРТФОЛИО: ✅ 200 OK (0.012s) +🧮 КАЛЬКУЛЯТОР: ✅ 200 OK (0.008s) +📸 РЕДАКТОР БАННЕРОВ: ✅ 302 (требует авторизации) +🎨 CSS ФАЙЛЫ: ✅ Все загружаются корректно +📁 UPLOADS ПАПКА: ✅ Создана и готова +``` + +## 🚀 Как использовать редактор баннеров: + +### **Шаг 1: Доступ** +``` +URL: http://localhost:3000/admin/banner-editor +Требуется: Авторизация в админ панели +``` + +### **Шаг 2: Загрузка изображений** +1. Нажать "Загрузить Изображения" +2. Перетащить файлы или выбрать через кнопку +3. Посмотреть превью и нажать "Загрузить" +4. Система автоматически создаст оптимизированные версии + +### **Шаг 3: Установка баннера** +1. Выбрать страницу во вкладках (Главная, О нас, Услуги, Портфолио) +2. Нажать "Использовать" на нужном изображении +3. Баннер мгновенно обновится +4. Настройки сохраняются автоматически + +### **Шаг 4: Управление** +- Удаление: кнопка "Удалить" в галерее +- Обновление: кнопка "Обновить" +- Сброс к градиенту: кнопка "Удалить" на текущем баннере + +## 🎯 Итоговое состояние: + +### ✅ **Что работает:** +- Главная страница с исправленными стилями +- Компактные баннеры на внутренних страницах +- Полнофункциональный редактор изображений +- API для загрузки и управления медиа +- Автоматическая оптимизация изображений +- Безопасная система аутентификации + +### 🔄 **Готово к использованию:** +- Сервер: `http://localhost:3000` (PID: 24059) +- Админка: `http://localhost:3000/admin` +- Редактор: `http://localhost:3000/admin/banner-editor` +- Папка загрузок: `/public/uploads/` (готова к использованию) + +### 📈 **Преимущества реализации:** +1. **Производительность**: WebP формат + множественные размеры +2. **UX**: Drag & Drop + мгновенные превью +3. **Безопасность**: Полная валидация + аутентификация +4. **Масштабируемость**: Готова к добавлению новых страниц +5. **Мобильность**: Отзывчивый дизайн на всех устройствах + +--- + +**🎉 Все задачи выполнены успешно! Система готова к продуктивному использованию.** \ No newline at end of file diff --git a/.history/config/database_20251019201726.js b/.history/config/database_20251019201726.js new file mode 100644 index 0000000..10b6a8f --- /dev/null +++ b/.history/config/database_20251019201726.js @@ -0,0 +1,30 @@ +const { Sequelize } = require('sequelize'); +require('dotenv').config(); + +const sequelize = new Sequelize(process.env.DATABASE_URL || { + host: process.env.DB_HOST || 'localhost', + port: process.env.DB_PORT || 5432, + database: process.env.DB_NAME || 'smartsoltech', + username: process.env.DB_USER || 'postgres', + password: process.env.DB_PASSWORD || 'password', + dialect: 'postgres', + logging: process.env.NODE_ENV === 'development' ? console.log : false, + pool: { + max: 5, + min: 0, + acquire: 30000, + idle: 10000 + } +}); + +// Test the connection +async function testConnection() { + try { + await sequelize.authenticate(); + console.log('✓ PostgreSQL connected successfully'); + } catch (error) { + console.error('✗ PostgreSQL connection error:', error); + } +} + +module.exports = { sequelize, testConnection }; \ No newline at end of file diff --git a/.history/config/database_20251019201735.js b/.history/config/database_20251019201735.js new file mode 100644 index 0000000..10b6a8f --- /dev/null +++ b/.history/config/database_20251019201735.js @@ -0,0 +1,30 @@ +const { Sequelize } = require('sequelize'); +require('dotenv').config(); + +const sequelize = new Sequelize(process.env.DATABASE_URL || { + host: process.env.DB_HOST || 'localhost', + port: process.env.DB_PORT || 5432, + database: process.env.DB_NAME || 'smartsoltech', + username: process.env.DB_USER || 'postgres', + password: process.env.DB_PASSWORD || 'password', + dialect: 'postgres', + logging: process.env.NODE_ENV === 'development' ? console.log : false, + pool: { + max: 5, + min: 0, + acquire: 30000, + idle: 10000 + } +}); + +// Test the connection +async function testConnection() { + try { + await sequelize.authenticate(); + console.log('✓ PostgreSQL connected successfully'); + } catch (error) { + console.error('✗ PostgreSQL connection error:', error); + } +} + +module.exports = { sequelize, testConnection }; \ No newline at end of file diff --git a/.history/locales/en_20251021183321.json b/.history/locales/en_20251021183321.json new file mode 100644 index 0000000..21143ff --- /dev/null +++ b/.history/locales/en_20251021183321.json @@ -0,0 +1,383 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "hero.title.smart", + "solutions": "hero.title.solutions" + }, + "subtitle": "Solutions", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "hero.cta.start", + "portfolio": "hero.cta.portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021183333.json b/.history/locales/en_20251021183333.json new file mode 100644 index 0000000..21143ff --- /dev/null +++ b/.history/locales/en_20251021183333.json @@ -0,0 +1,383 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "hero.title.smart", + "solutions": "hero.title.solutions" + }, + "subtitle": "Solutions", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "hero.cta.start", + "portfolio": "hero.cta.portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021184946.json b/.history/locales/en_20251021184946.json new file mode 100644 index 0000000..733cff5 --- /dev/null +++ b/.history/locales/en_20251021184946.json @@ -0,0 +1,383 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185005.json b/.history/locales/en_20251021185005.json new file mode 100644 index 0000000..64f6e28 --- /dev/null +++ b/.history/locales/en_20251021185005.json @@ -0,0 +1,410 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185016.json b/.history/locales/en_20251021185016.json new file mode 100644 index 0000000..98a74f6 --- /dev/null +++ b/.history/locales/en_20251021185016.json @@ -0,0 +1,431 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185033.json b/.history/locales/en_20251021185033.json new file mode 100644 index 0000000..266ba3a --- /dev/null +++ b/.history/locales/en_20251021185033.json @@ -0,0 +1,435 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185044.json b/.history/locales/en_20251021185044.json new file mode 100644 index 0000000..fc3bd8c --- /dev/null +++ b/.history/locales/en_20251021185044.json @@ -0,0 +1,441 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185051.json b/.history/locales/en_20251021185051.json new file mode 100644 index 0000000..3983732 --- /dev/null +++ b/.history/locales/en_20251021185051.json @@ -0,0 +1,441 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185058.json b/.history/locales/en_20251021185058.json new file mode 100644 index 0000000..653a3d9 --- /dev/null +++ b/.history/locales/en_20251021185058.json @@ -0,0 +1,441 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185105.json b/.history/locales/en_20251021185105.json new file mode 100644 index 0000000..7e51b81 --- /dev/null +++ b/.history/locales/en_20251021185105.json @@ -0,0 +1,441 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185114.json b/.history/locales/en_20251021185114.json new file mode 100644 index 0000000..cbf7b8c --- /dev/null +++ b/.history/locales/en_20251021185114.json @@ -0,0 +1,449 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "Become a Partner for Success Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021185126.json b/.history/locales/en_20251021185126.json new file mode 100644 index 0000000..250e393 --- /dev/null +++ b/.history/locales/en_20251021185126.json @@ -0,0 +1,473 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "We'll Grow Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021190951.json b/.history/locales/en_20251021190951.json new file mode 100644 index 0000000..250e393 --- /dev/null +++ b/.history/locales/en_20251021190951.json @@ -0,0 +1,473 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "We'll Grow Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021205934.json b/.history/locales/en_20251021205934.json new file mode 100644 index 0000000..1b9134d --- /dev/null +++ b/.history/locales/en_20251021205934.json @@ -0,0 +1,477 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "We'll Grow Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021205945.json b/.history/locales/en_20251021205945.json new file mode 100644 index 0000000..642345f --- /dev/null +++ b/.history/locales/en_20251021205945.json @@ -0,0 +1,478 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "We'll Grow Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021210243.json b/.history/locales/en_20251021210243.json new file mode 100644 index 0000000..2505905 --- /dev/null +++ b/.history/locales/en_20251021210243.json @@ -0,0 +1,483 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00 - 18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "We respond within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + }, + "address": { + "line1": "Office Address", + "line2": "123 Teheran-ro, Gangnam-gu" + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "We'll Grow Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021210341.json b/.history/locales/en_20251021210341.json new file mode 100644 index 0000000..2505905 --- /dev/null +++ b/.history/locales/en_20251021210341.json @@ -0,0 +1,483 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "title_highlight": "Services", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "web_development": { + "title": "Web Development", + "description": "Modern and responsive websites and web applications development", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Mobile App", + "description": "Native and cross-platform apps for iOS and Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX Design", + "description": "User-centered intuitive and beautiful interface design", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Digital Marketing", + "description": "Digital marketing through SEO, social media, online advertising", + "price": "$2,000~" + }, + "view_all": "View All Services", + "subtitle": "Professional development services to turn your ideas into reality", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "subtitle": "Check out successfully completed projects", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + }, + "step1": { + "title": "Step 1: Service Selection", + "subtitle": "Please select the services you need (multiple selection allowed)" + }, + "step2": { + "title": "Step 2: Project Details", + "subtitle": "Select project complexity and timeline" + }, + "complexity": { + "title": "Project Complexity", + "simple": "Simple", + "simple_desc": "Basic features, standard design", + "medium": "Medium", + "medium_desc": "Additional features, custom design", + "complex": "Complex", + "complex_desc": "Advanced features, complex integrations" + }, + "timeline": { + "title": "Development Timeline", + "standard": "Standard", + "standard_desc": "Normal development timeframe", + "rush": "Rush", + "rush_desc": "Fast development (+50%)", + "extended": "Extended", + "extended_desc": "Flexible development timeline (-20%)" + }, + "result": { + "title": "Estimate Results", + "subtitle": "Here's your preliminary project cost estimate", + "estimated_price": "Estimated Price", + "price_note": "* Final cost may vary based on project details", + "summary": "Project Summary", + "selected_services": "Selected Services", + "complexity": "Complexity", + "timeline": "Timeline", + "get_quote": "Get Accurate Quote", + "recalculate": "Recalculate", + "contact_note": "Contact us for an accurate quote and to discuss project details" + }, + "next_step": "Next Step", + "prev_step": "Previous", + "calculate": "Calculate" + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "Name", + "email": "Email", + "phone": "Phone", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "Please briefly describe your project", + "submit": "Apply for Consultation", + "title": "Project Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00 - 18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "We respond within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + }, + "address": { + "line1": "Office Address", + "line2": "123 Teheran-ro, Gangnam-gu" + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "We'll Grow Together", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "Grow your business with innovative technology" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "Quick Links", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved.", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021210347.json b/.history/locales/en_20251021210347.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.history/locales/en_20251021210347.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/.history/locales/en_20251021210512.json b/.history/locales/en_20251021210512.json new file mode 100644 index 0000000..52e83eb --- /dev/null +++ b/.history/locales/en_20251021210512.json @@ -0,0 +1,286 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021210629.json b/.history/locales/en_20251021210629.json new file mode 100644 index 0000000..52e83eb --- /dev/null +++ b/.history/locales/en_20251021210629.json @@ -0,0 +1,286 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "service": { + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021210647.json b/.history/locales/en_20251021210647.json new file mode 100644 index 0000000..97451a5 --- /dev/null +++ b/.history/locales/en_20251021210647.json @@ -0,0 +1,292 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry", + "service": { + "title": "Service Interest", + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "info": { + "title": "Contact Information" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021210656.json b/.history/locales/en_20251021210656.json new file mode 100644 index 0000000..6ad919a --- /dev/null +++ b/.history/locales/en_20251021210656.json @@ -0,0 +1,299 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry", + "service": { + "title": "Service Interest", + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "info": { + "title": "Contact Information" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00-18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "Response within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "address": { + "title": "Office Address", + "line1": "123 Teheran-ro, Gangnam-gu", + "line2": "Seoul, South Korea" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021211404.json b/.history/locales/en_20251021211404.json new file mode 100644 index 0000000..64bfc8b --- /dev/null +++ b/.history/locales/en_20251021211404.json @@ -0,0 +1,331 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry", + "service": { + "title": "Service Interest", + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "info": { + "title": "Contact Information" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00-18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "Response within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "address": { + "title": "Office Address", + "line1": "123 Teheran-ro, Gangnam-gu", + "line2": "Seoul, South Korea" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "portfolio_page": { + "title": "Our Portfolio", + "subtitle": "Discover innovative projects and creative solutions", + "categories": { + "all": "All", + "web-development": "Web Development", + "mobile-app": "Mobile App", + "ui-ux-design": "UI/UX Design", + "branding": "Branding", + "marketing": "Digital Marketing" + }, + "buttons": { + "details": "View Details", + "projectDetails": "Project Details", + "loadMore": "Load More Projects", + "contact": "Request Project", + "calculate": "Calculate Cost" + }, + "empty": { + "title": "No portfolio yet", + "subtitle": "We'll be showcasing amazing projects soon!" + }, + "cta": { + "title": "Be the star of the next project", + "subtitle": "Create innovative digital solutions with us" + }, + "labels": { + "featured": "FEATURED", + "views": "views", + "likes": "likes" + } + } +} \ No newline at end of file diff --git a/.history/locales/en_20251021211513.json b/.history/locales/en_20251021211513.json new file mode 100644 index 0000000..64bfc8b --- /dev/null +++ b/.history/locales/en_20251021211513.json @@ -0,0 +1,331 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry", + "service": { + "title": "Service Interest", + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "info": { + "title": "Contact Information" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00-18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "Response within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "address": { + "title": "Office Address", + "line1": "123 Teheran-ro, Gangnam-gu", + "line2": "Seoul, South Korea" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "portfolio_page": { + "title": "Our Portfolio", + "subtitle": "Discover innovative projects and creative solutions", + "categories": { + "all": "All", + "web-development": "Web Development", + "mobile-app": "Mobile App", + "ui-ux-design": "UI/UX Design", + "branding": "Branding", + "marketing": "Digital Marketing" + }, + "buttons": { + "details": "View Details", + "projectDetails": "Project Details", + "loadMore": "Load More Projects", + "contact": "Request Project", + "calculate": "Calculate Cost" + }, + "empty": { + "title": "No portfolio yet", + "subtitle": "We'll be showcasing amazing projects soon!" + }, + "cta": { + "title": "Be the star of the next project", + "subtitle": "Create innovative digital solutions with us" + }, + "labels": { + "featured": "FEATURED", + "views": "views", + "likes": "likes" + } + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251019203946.json b/.history/locales/ko_20251019203946.json new file mode 100644 index 0000000..dd925e3 --- /dev/null +++ b/.history/locales/ko_20251019203946.json @@ -0,0 +1,254 @@ +{ + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기", + "contact": "문의하기" + }, + "language": { + "ko": "한국어", + "korean": "한국어", + "english": "영어", + "russian": "러시아어", + "kazakh": "카자흐어" + }, + "theme": { + "toggle": "테마 전환" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "view_all": "모든 서비스 보기" + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_all": "모든 프로젝트 보기", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + } + }, + "common": { + "view_details": "자세히 보기" + }, + "about": { + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요" + } + }, + "contact": { + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "message": "메시지", + "submit": "문의 보내기", + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + } + }, + "calculator": { + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기", + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간" + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "social": { + "follow": "팔로우하기" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251019204000.json b/.history/locales/ko_20251019204000.json new file mode 100644 index 0000000..dd925e3 --- /dev/null +++ b/.history/locales/ko_20251019204000.json @@ -0,0 +1,254 @@ +{ + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기", + "contact": "문의하기" + }, + "language": { + "ko": "한국어", + "korean": "한국어", + "english": "영어", + "russian": "러시아어", + "kazakh": "카자흐어" + }, + "theme": { + "toggle": "테마 전환" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "view_all": "모든 서비스 보기" + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_all": "모든 프로젝트 보기", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + } + }, + "common": { + "view_details": "자세히 보기" + }, + "about": { + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요" + } + }, + "contact": { + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "message": "메시지", + "submit": "문의 보내기", + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + } + }, + "calculator": { + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기", + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간" + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "social": { + "follow": "팔로우하기" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021185144.json b/.history/locales/ko_20251021185144.json new file mode 100644 index 0000000..73fd3b7 --- /dev/null +++ b/.history/locales/ko_20251021185144.json @@ -0,0 +1,429 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta_primary": "Start Project", + "cta_secondary": "View Portfolio", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "title_highlight": "서비스", + "description": "최첨단 기술과 창의적 아이디어로 완성된 디지털 솔루션", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + }, + "view_all": "모든 서비스 보기", + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + } + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "메시지", + "submit": "문의 보내기", + "title": "프로젝트 문의", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "함께 성장하겠습니다", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "당신의 아이디어를 현실로 만들어보세요" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021185152.json b/.history/locales/ko_20251021185152.json new file mode 100644 index 0000000..3878de2 --- /dev/null +++ b/.history/locales/ko_20251021185152.json @@ -0,0 +1,429 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "title_highlight": "서비스", + "description": "최첨단 기술과 창의적 아이디어로 완성된 디지털 솔루션", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + }, + "view_all": "모든 서비스 보기", + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + } + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "메시지", + "submit": "문의 보내기", + "title": "프로젝트 문의", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "함께 성장하겠습니다", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "당신의 아이디어를 현실로 만들어보세요" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021190951.json b/.history/locales/ko_20251021190951.json new file mode 100644 index 0000000..3878de2 --- /dev/null +++ b/.history/locales/ko_20251021190951.json @@ -0,0 +1,429 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "title_highlight": "서비스", + "description": "최첨단 기술과 창의적 아이디어로 완성된 디지털 솔루션", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + }, + "view_all": "모든 서비스 보기", + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + } + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "메시지", + "submit": "문의 보내기", + "title": "프로젝트 문의", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "함께 성장하겠습니다", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "당신의 아이디어를 현실로 만들어보세요" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021210103.json b/.history/locales/ko_20251021210103.json new file mode 100644 index 0000000..a7414ef --- /dev/null +++ b/.history/locales/ko_20251021210103.json @@ -0,0 +1,481 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "title_highlight": "서비스", + "description": "최첨단 기술과 창의적 아이디어로 완성된 디지털 솔루션", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + }, + "view_all": "모든 서비스 보기", + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "메시지", + "submit": "문의 보내기", + "title": "프로젝트 문의", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "함께 성장하겠습니다", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021210120.json b/.history/locales/ko_20251021210120.json new file mode 100644 index 0000000..a97fe4b --- /dev/null +++ b/.history/locales/ko_20251021210120.json @@ -0,0 +1,482 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "title_highlight": "서비스", + "description": "최첨단 기술과 창의적 아이디어로 완성된 디지털 솔루션", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + }, + "view_all": "모든 서비스 보기", + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "메시지", + "submit": "문의 보내기", + "title": "프로젝트 문의", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "함께 성장하겠습니다", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021210347.json b/.history/locales/ko_20251021210347.json new file mode 100644 index 0000000..a97fe4b --- /dev/null +++ b/.history/locales/ko_20251021210347.json @@ -0,0 +1,482 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + } + }, + "services": { + "title": { + "our": "우리의", + "services": "서비스" + }, + "title_highlight": "서비스", + "description": "최첨단 기술과 창의적 아이디어로 완성된 디지털 솔루션", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + }, + "view_all": "모든 서비스 보기", + "subtitle": "전문적인 개발 서비스로 당신의 아이디어를 현실로 만들어드립니다", + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "title_highlight": "Projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "view_project": "프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + } + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application", + "form": { + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "message": "메시지", + "submit": "문의 보내기", + "title": "프로젝트 문의", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + } + }, + "about": { + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "values": { + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + } + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + }, + "cta": { + "title": "함께 성장하겠습니다", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + } + }, + "footer": { + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "description": "Digital solution specialist leading innovation", + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard": "Dashboard", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "title": "SmartSolTech Admin", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "description": "Digital solution specialist leading innovation", + "tagline": "Future begins here", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "contact_us": "Contact us", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211024.json b/.history/locales/ko_20251021211024.json new file mode 100644 index 0000000..7aa2067 --- /dev/null +++ b/.history/locales/ko_20251021211024.json @@ -0,0 +1,500 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + }, + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기" + }, + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + }, + "title_highlight": "서비스", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + }, + "title_highlight": "Projects", + "view_project": "프로젝트 보기" + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "message": "메시지", + "submit": "문의 보내기", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "form": { + "title": "프로젝트 문의", + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다", + "service": { + "title": "관심 서비스" + } + }, + "info": { + "title": "연락처 정보" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678", + "hours": "월-금 9:00-18:00" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr", + "response": "24시간 내 응답" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "address": { + "title": "사무실 주소", + "line1": "테헤란로 123, 강남구", + "line2": "서울, 대한민국" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application" + }, + "about": { + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + }, + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "tagline": "Future begins here", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211047.json b/.history/locales/ko_20251021211047.json new file mode 100644 index 0000000..81687c8 --- /dev/null +++ b/.history/locales/ko_20251021211047.json @@ -0,0 +1,492 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + }, + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기" + }, + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + }, + "title_highlight": "서비스", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + }, + "title_highlight": "Projects", + "view_project": "프로젝트 보기" + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "message": "메시지", + "submit": "문의 보내기", + "service": { + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + }, + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "info": { + "title": "연락처 정보" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678", + "hours": "월-금 9:00-18:00" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr", + "response": "24시간 내 응답" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "address": { + "title": "사무실 주소", + "line1": "테헤란로 123, 강남구", + "line2": "서울, 대한민국" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application" + }, + "about": { + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + }, + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "tagline": "Future begins here", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211057.json b/.history/locales/ko_20251021211057.json new file mode 100644 index 0000000..e4a476d --- /dev/null +++ b/.history/locales/ko_20251021211057.json @@ -0,0 +1,496 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + }, + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기" + }, + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + }, + "title_highlight": "서비스", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + }, + "title_highlight": "Projects", + "view_project": "프로젝트 보기" + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "message": "메시지", + "submit": "문의 보내기", + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다", + "service": { + "title": "관심 서비스", + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + } + }, + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "info": { + "title": "연락처 정보" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678", + "hours": "월-금 9:00-18:00" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr", + "response": "24시간 내 응답" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "address": { + "title": "사무실 주소", + "line1": "테헤란로 123, 강남구", + "line2": "서울, 대한민국" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application" + }, + "about": { + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + }, + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "tagline": "Future begins here", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211426.json b/.history/locales/ko_20251021211426.json new file mode 100644 index 0000000..50922bc --- /dev/null +++ b/.history/locales/ko_20251021211426.json @@ -0,0 +1,528 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + }, + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기" + }, + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + }, + "title_highlight": "서비스", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + }, + "title_highlight": "Projects", + "view_project": "프로젝트 보기" + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "message": "메시지", + "submit": "문의 보내기", + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다", + "service": { + "title": "관심 서비스", + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + } + }, + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "info": { + "title": "연락처 정보" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678", + "hours": "월-금 9:00-18:00" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr", + "response": "24시간 내 응답" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "address": { + "title": "사무실 주소", + "line1": "테헤란로 123, 강남구", + "line2": "서울, 대한민국" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application" + }, + "about": { + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + }, + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "tagline": "Future begins here", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "portfolio_page": { + "title": "우리의 포트폴리오", + "subtitle": "혁신적인 프로젝트와 창의적인 솔루션들을 만나보세요", + "categories": { + "all": "전체", + "web-development": "웹 개발", + "mobile-app": "모바일 앱", + "ui-ux-design": "UI/UX 디자인", + "branding": "브랜딩", + "marketing": "디지털 마케팅" + }, + "buttons": { + "details": "자세히 보기", + "projectDetails": "프로젝트 상세보기", + "loadMore": "더 많은 프로젝트 보기", + "contact": "프로젝트 문의하기", + "calculate": "비용 계산하기" + }, + "empty": { + "title": "아직 포트폴리오가 없습니다", + "subtitle": "곧 멋진 프로젝트들을 공개할 예정입니다!" + }, + "cta": { + "title": "다음 프로젝트의 주인공이 되어보세요", + "subtitle": "우리와 함께 혁신적인 디지털 솔루션을 만들어보세요" + }, + "labels": { + "featured": "FEATURED", + "views": "조회수", + "likes": "좋아요" + } + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211513.json b/.history/locales/ko_20251021211513.json new file mode 100644 index 0000000..50922bc --- /dev/null +++ b/.history/locales/ko_20251021211513.json @@ -0,0 +1,528 @@ +{ + "navigation": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "contact": "문의하기", + "calculator": "견적 계산기", + "admin": "Admin", + "home - SmartSolTech": "navigation.home - SmartSolTech" + }, + "hero": { + "title": { + "smart": "스마트", + "solutions": "솔루션" + }, + "subtitle": "혁신적인 기술로 당신의 비즈니스를 성장시키세요", + "description": "혁신적인 웹 개발, 모바일 앱, UI/UX 디자인으로 비�니스 디지털 변혁을 이끕니다", + "cta": { + "start": "시작하기", + "portfolio": "포트폴리오 보기" + }, + "cta_primary": "프로젝트 시작", + "cta_secondary": "포트폴리오 보기" + }, + "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, SNS 마케팅, 광고 운영", + "price": "₩200,000부터" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements and" + } + }, + "title_highlight": "서비스", + "web_development": { + "title": "웹 개발", + "description": "현대적이고 반응형 웹사이트 및 웹 애플리케이션 개발", + "price": "₩500만원~" + }, + "mobile_app": { + "title": "모바일 앱", + "description": "iOS와 Android용 네이티브 및 크로스 플랫폼 앱", + "price": "₩800만원~" + }, + "ui_ux_design": { + "title": "UI/UX 디자인", + "description": "사용자 중심의 직관적이고 아름다운 인터페이스 디자인", + "price": "₩300만원~" + }, + "digital_marketing": { + "title": "디지털 마케팅", + "description": "SEO, 소셜미디어, 온라인 광고를 통한 디지털 마케팅", + "price": "₩200만원~" + } + }, + "portfolio": { + "title": { + "recent": "최근", + "projects": "프로젝트", + "our": "우리의", + "portfolio": "포트폴리오" + }, + "subtitle": "성공적으로 완료한 프로젝트들을 확인해보세요", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "모든 프로젝트 보기", + "categories": { + "all": "전체", + "web": "웹 개발", + "mobile": "모바일 앱", + "uiux": "UI/UX 디자인" + }, + "project_details": "프로젝트 상세보기", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech", + "og_title": "Portfolio - SmartSolTech", + "og_description": "SmartSolTech's diverse projects and success stories" + }, + "title_highlight": "Projects", + "view_project": "프로젝트 보기" + }, + "calculator": { + "title": "견적 계산기", + "subtitle": "프로젝트 예상 비용을 확인해보세요", + "meta": { + "title": "견적 계산기", + "description": "프로젝트 예상 비용을 간편하게 계산해보세요" + }, + "cta": { + "title": "정확한 견적이 필요하신가요?", + "subtitle": "간단한 정보로 예상 비용을 확인하세요", + "button": "견적 계산하기" + }, + "step1": { + "title": "1단계: 서비스 선택", + "subtitle": "필요한 서비스를 선택해주세요" + }, + "step2": { + "title": "2단계: 옵션 선택", + "subtitle": "프로젝트 세부사항을 선택해주세요" + }, + "complexity": { + "title": "프로젝트 복잡도", + "simple": "단순", + "simple_desc": "기본적인 기능", + "medium": "보통", + "medium_desc": "표준 기능", + "complex": "복잡", + "complex_desc": "고급 기능" + }, + "timeline": { + "title": "개발 기간", + "standard": "표준", + "standard_desc": "일반적인 개발 기간", + "rush": "급행", + "rush_desc": "빠른 개발 (추가 비용)", + "extended": "여유", + "extended_desc": "충분한 개발 기간 (할인)" + }, + "result": { + "title": "견적 결과", + "subtitle": "프로젝트 예상 비용입니다", + "estimated_price": "예상 비용", + "price_note": "* 정확한 견적은 상담 후 확정됩니다", + "summary": "견적 요약", + "selected_services": "선택된 서비스", + "complexity": "복잡도", + "timeline": "개발 기간", + "get_quote": "정확한 견적 요청", + "recalculate": "다시 계산하기", + "contact_note": "더 정확한 견적을 위해 상담을 받아보세요" + }, + "next_step": "다음 단계", + "prev_step": "이전 단계", + "calculate": "견적 계산하기" + }, + "contact": { + "hero": { + "title": "문의하기", + "subtitle": "여러분의 아이디어를 현실로 만들어드립니다" + }, + "ready_title": "프로젝트를 시작할 준비가 되셨나요?", + "ready_description": "아이디어를 현실로 바꿔보세요. 전문가가 최고의 솔루션을 제공합니다.", + "form": { + "title": "프로젝트 문의", + "name": "이름", + "email": "이메일", + "phone": "전화번호", + "message": "메시지", + "submit": "문의 보내기", + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다", + "service": { + "title": "관심 서비스", + "select": "관심 서비스를 선택하세요", + "web": "웹 개발", + "mobile": "모바일 앱", + "design": "UI/UX 디자인", + "branding": "브랜딩", + "consulting": "컨설팅", + "other": "기타" + } + }, + "service_interest": "Service Interest", + "service_options": { + "select": "Select Service Interest", + "web_development": "Web Development", + "mobile_app": "Mobile App", + "ui_ux_design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + }, + "success": "문의가 성공적으로 전송되었습니다", + "error": "문의 전송 중 오류가 발생했습니다" + }, + "info": { + "title": "연락처 정보" + }, + "phone": { + "title": "전화 문의", + "number": "+82-2-1234-5678", + "hours": "월-금 9:00-18:00" + }, + "email": { + "title": "이메일 문의", + "address": "info@smartsoltech.co.kr", + "response": "24시간 내 응답" + }, + "telegram": { + "title": "텔레그램", + "subtitle": "빠른 응답을 원하신다면" + }, + "address": { + "title": "사무실 주소", + "line1": "테헤란로 123, 강남구", + "line2": "서울, 대한민국" + }, + "cta": { + "ready": "준비되셨나요?", + "start": "시작해보세요", + "question": "질문이 있으신가요?", + "subtitle": "프로젝트에 대해 상담해드립니다" + }, + "meta": { + "title": "문의하기", + "description": "프로젝트 문의나 상담이 필요하시면 언제든 연락주세요" + }, + "phone_consultation": "Phone Consultation", + "email_inquiry": "Email Inquiry", + "telegram_chat": "Telegram Chat", + "instant_response": "Instant response available", + "free_consultation": "Free Consultation Application" + }, + "about": { + "hero": { + "title": "스마트솔테크 소개", + "subtitle": "혁신과 기술로 미래를 만들어갑니다" + }, + "company": { + "title": "회사 정보", + "description1": "스마트솔테크는 2020년 설립된 기술 전문 회사로, 웹 개발, 모바일 앱 개발, UI/UX 디자인 분야에서 전문성을 인정받고 있습니다.", + "description2": "우리는 고객의 니즈를 정확히 파악하고, 최신 기술을 활용하여 혁신적인 솔루션을 제공합니다." + }, + "stats": { + "projects": "완료된 프로젝트", + "experience": "년간 경험", + "clients": "만족한 고객" + }, + "mission": { + "title": "우리의 미션", + "description": "기술을 통해 고객의 비즈니스 성장을 지원하고, 디지털 혁신을 이끌어나가는 것이 우리의 사명입니다." + }, + "values": { + "innovation": { + "title": "혁신", + "description": "최신 기술과 트렌드를 빠르게 적용하여 혁신적인 솔루션을 제공합니다." + }, + "quality": { + "title": "품질", + "description": "높은 품질의 코드와 디자인으로 안정적이고 우수한 제품을 개발합니다." + }, + "partnership": { + "title": "파트너십", + "description": "고객과의 긴밀한 협력을 통해 최상의 결과를 만들어냅니다." + }, + "title": "Core", + "title_highlight": "Values", + "description": "Core values pursued by SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Growth", + "description": "We grow together with customers and pursue continuous learning and development." + } + }, + "cta": { + "title": "함께 성장하겠습니다", + "subtitle": "당신의 아이디어를 현실로 만들어보세요", + "button": "Contact Us", + "description": "Take your business to the next level with SmartSolTech", + "partnership": "Partnership Inquiry", + "portfolio": "View Portfolio" + }, + "meta": { + "title": "회사소개", + "description": "스마트솔테크는 혁신적인 기술로 고객의 비즈니스 성장을 지원하는 전문 개발 회사입니다" + }, + "hero_title": "About", + "hero_highlight": "SmartSolTech", + "hero_description": "Digital solution specialist leading customer success with innovative technology", + "overview": { + "title": "Creating Future with Innovation and Creativity", + "description_1": "SmartSolTech is a digital solution specialist established in 2020, supporting customer business success with innovative technology and creative ideas in web development, mobile apps, and UI/UX design.", + "description_2": "We don't just provide technology, but understand customer goals and propose optimal solutions to become partners growing together.", + "stats": { + "projects": "100+", + "projects_label": "Completed Projects", + "clients": "50+", + "clients_label": "Satisfied Customers", + "experience": "4 years", + "experience_label": "Industry Experience" + }, + "mission": "Our Mission", + "mission_text": "Helping all businesses succeed in the digital age through technology", + "vision": "Our Vision", + "vision_text": "Growing as a global digital solution company representing Korea to lead digital innovation for customers worldwide" + }, + "team": { + "title": "Our", + "title_highlight": "Team", + "description": "Introducing the SmartSolTech team with expertise and passion" + }, + "tech_stack": { + "title": "Technology", + "title_highlight": "Stack", + "description": "We provide the best solutions with cutting-edge technology and proven tools", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Mobile" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "빠른 링크", + "privacy": "개인정보처리방침", + "terms": "이용약관", + "sitemap": "사이트맵" + }, + "contact": { + "title": "연락처", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "서울특별시 강남구 테헤란로 123" + }, + "copyright": "© 2024 스마트솔테크. 모든 권리 보유.", + "company": { + "description": "혁신적인 기술로 당신의 비즈니스를 성장시키세요" + }, + "quick_links": "Quick Links", + "services": "Services", + "contact_info": "Contact Information", + "follow_us": "Follow Us", + "rights": "All rights reserved.", + "privacy": "개인정보보호", + "terms": "이용약관", + "social": { + "follow": "팔로우하기" + } + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "테마 전환" + }, + "language": { + "english": "영어", + "korean": "한국어", + "russian": "러시아어", + "kazakh": "카자흐어", + "ko": "한국어" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "자세히 보기" + }, + "meta": { + "description": "스마트솔테크 - 혁신적인 웹 개발, 모바일 앱 개발, UI/UX 디자인 서비스", + "keywords": "웹 개발, 모바일 앱, UI/UX 디자인, 한국", + "title": "스마트솔테크" + }, + "nav": { + "home": "홈", + "about": "회사소개", + "services": "서비스", + "portfolio": "포트폴리오", + "calculator": "견적 계산기" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin", + "login_title": "Admin Panel Login", + "login_subtitle": "Login to your account to manage the site", + "login_button": "Login", + "email": "Email", + "password": "Password", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Enter password", + "back_to_site": "Back to site", + "dashboard_subtitle": "Overview of main site metrics", + "portfolio": "Portfolio", + "services": "Services", + "contacts": "Messages", + "settings": "Settings", + "users": "Users", + "logout": "Logout", + "view_site": "View site", + "view_all": "View all", + "portfolio_projects": "Projects", + "contact_messages": "Messages", + "recent_portfolio": "Recent projects", + "recent_contacts": "Recent messages", + "no_recent_portfolio": "No recent projects", + "no_recent_contacts": "No recent messages", + "quick_actions": "Quick actions", + "add_portfolio": "Add project", + "add_service": "Add service", + "site_settings": "Site settings", + "banner_editor": "Banner Editor", + "current_banner": "Current banner", + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Innovative Technology Solutions", + "tagline": "Future begins here", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support", + "contact_us": "Contact us" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "portfolio_page": { + "title": "우리의 포트폴리오", + "subtitle": "혁신적인 프로젝트와 창의적인 솔루션들을 만나보세요", + "categories": { + "all": "전체", + "web-development": "웹 개발", + "mobile-app": "모바일 앱", + "ui-ux-design": "UI/UX 디자인", + "branding": "브랜딩", + "marketing": "디지털 마케팅" + }, + "buttons": { + "details": "자세히 보기", + "projectDetails": "프로젝트 상세보기", + "loadMore": "더 많은 프로젝트 보기", + "contact": "프로젝트 문의하기", + "calculate": "비용 계산하기" + }, + "empty": { + "title": "아직 포트폴리오가 없습니다", + "subtitle": "곧 멋진 프로젝트들을 공개할 예정입니다!" + }, + "cta": { + "title": "다음 프로젝트의 주인공이 되어보세요", + "subtitle": "우리와 함께 혁신적인 디지털 솔루션을 만들어보세요" + }, + "labels": { + "featured": "FEATURED", + "views": "조회수", + "likes": "좋아요" + } + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211904.json b/.history/locales/ko_20251021211904.json new file mode 100644 index 0000000..ea46c6e --- /dev/null +++ b/.history/locales/ko_20251021211904.json @@ -0,0 +1,331 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry", + "service": { + "title": "Service Interest", + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "info": { + "title": "Contact Information" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00-18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "Response within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "address": { + "title": "Office Address", + "line1": "123 Teheran-ro, Gangnam-gu", + "line2": "Seoul, South Korea" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "portfolio_page": { + "title": "우리의 포트폴리오", + "subtitle": "혁신적인 프로젝트와 창의적인 솔루션들을 만나보세요", + "categories": { + "all": "전체", + "web-development": "웹 개발", + "mobile-app": "모바일 앱", + "ui-ux-design": "UI/UX 디자인", + "branding": "브랜딩", + "marketing": "디지털 마케팅" + }, + "buttons": { + "details": "자세히 보기", + "projectDetails": "프로젝트 상세보기", + "loadMore": "더 많은 프로젝트 보기", + "contact": "프로젝트 문의하기", + "calculate": "비용 계산하기" + }, + "empty": { + "title": "아직 포트폴리오가 없습니다", + "subtitle": "곧 멋진 프로젝트들을 공개할 예정입니다!" + }, + "cta": { + "title": "다음 프로젝트의 주인공이 되어보세요", + "subtitle": "우리와 함께 혁신적인 디지털 솔루션을 만들어보세요" + }, + "labels": { + "featured": "추천", + "views": "조회수", + "likes": "좋아요" + } + } +} \ No newline at end of file diff --git a/.history/locales/ko_20251021211925.json b/.history/locales/ko_20251021211925.json new file mode 100644 index 0000000..ea46c6e --- /dev/null +++ b/.history/locales/ko_20251021211925.json @@ -0,0 +1,331 @@ +{ + "navigation": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator", + "admin": "Admin" + }, + "hero": { + "title": { + "smart": "Smart", + "solutions": "Solutions" + }, + "subtitle": "Grow your business with innovative technology", + "description": "Innovative web development, mobile apps, UI/UX design leading your business digital transformation", + "cta": { + "start": "Get Started", + "portfolio": "View Portfolio" + } + }, + "services": { + "title": { + "our": "Our", + "services": "Services" + }, + "subtitle": "Professional development services to turn your ideas into reality", + "description": "Digital solutions completed with cutting-edge technology and creative ideas", + "view_all": "View All Services", + "web": { + "title": "Web Development", + "description": "Responsive websites and web application development", + "price": "From $500" + }, + "mobile": { + "title": "Mobile Apps", + "description": "iOS and Android native app development", + "price": "From $1,000" + }, + "design": { + "title": "UI/UX Design", + "description": "User-centered interface and experience design", + "price": "From $300" + }, + "marketing": { + "title": "Digital Marketing", + "description": "SEO, social media marketing, advertising management", + "price": "From $200" + }, + "meta": { + "title": "Services", + "description": "Check out SmartSolTech's professional services. Web development, mobile apps, UI/UX design, digital marketing and other technology solutions.", + "keywords": "web development, mobile apps, UI/UX design, digital marketing, technology solutions, SmartSolTech" + }, + "hero": { + "title": "Our", + "title_highlight": "Services", + "subtitle": "Support business growth with innovative technology" + }, + "cards": { + "starting_price": "Starting Price", + "consultation": "consultation", + "contact": "Contact", + "calculate_cost": "Calculate Cost", + "popular": "Popular", + "coming_soon": "Services Coming Soon", + "coming_soon_desc": "We'll soon offer various services!" + }, + "process": { + "title": "Project Implementation Process", + "subtitle": "We conduct projects with systematic and professional processes", + "consultation": { + "title": "Consultation and Planning", + "description": "Accurately understand customer requirements" + } + } + }, + "portfolio": { + "title": { + "recent": "Recent", + "projects": "Projects" + }, + "subtitle": "Check out successfully completed projects", + "description": "Check out the projects completed for customer success", + "view_details": "View Details", + "view_all": "View All Portfolio", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "project_details": "Project Details", + "default": { + "ecommerce": "E-commerce", + "title": "E-commerce Platform", + "description": "Modern online commerce solution with intuitive interface" + }, + "meta": { + "title": "Portfolio", + "description": "Check out SmartSolTech's diverse projects and success stories. Web development, mobile apps, UI/UX design portfolio.", + "keywords": "portfolio, web development, mobile apps, UI/UX design, projects, SmartSolTech" + } + }, + "calculator": { + "title": "Project Cost Calculator", + "subtitle": "Select your desired services and requirements to get accurate cost estimates in real time", + "meta": { + "title": "Project Cost Calculator", + "description": "Calculate the cost of your web development, mobile app, or design project with our interactive calculator" + }, + "cta": { + "title": "Check Your Project Estimate", + "subtitle": "Select your desired services and requirements to calculate costs in real time", + "button": "Use Cost Calculator" + } + }, + "contact": { + "hero": { + "title": "Contact Us", + "subtitle": "We're here to help bring your ideas to life" + }, + "ready_title": "Ready to Start Your Project?", + "ready_description": "Turn your ideas into reality. Experts provide the best solutions.", + "form": { + "title": "Project Inquiry", + "name": "Name", + "email": "Email", + "phone": "Phone", + "message": "Message", + "submit": "Send Inquiry", + "success": "Inquiry sent successfully", + "error": "Error occurred while sending inquiry", + "service": { + "title": "Service Interest", + "select": "Select service of interest", + "web": "Web Development", + "mobile": "Mobile App", + "design": "UI/UX Design", + "branding": "Branding", + "consulting": "Consulting", + "other": "Other" + } + }, + "info": { + "title": "Contact Information" + }, + "phone": { + "title": "Phone Inquiry", + "number": "+82-2-1234-5678", + "hours": "Mon-Fri 9:00-18:00" + }, + "email": { + "title": "Email Inquiry", + "address": "info@smartsoltech.co.kr", + "response": "Response within 24 hours" + }, + "telegram": { + "title": "Telegram", + "subtitle": "For quick response" + }, + "address": { + "title": "Office Address", + "line1": "123 Teheran-ro, Gangnam-gu", + "line2": "Seoul, South Korea" + }, + "cta": { + "ready": "Ready?", + "start": "Get Started", + "question": "Have questions?", + "subtitle": "We provide consultation on projects" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Innovation", + "description": "We provide innovative solutions through continuous R&D and adoption of cutting-edge technology." + }, + "quality": { + "title": "Quality", + "description": "We maintain high quality standards and provide high-quality products that customers can be satisfied with." + }, + "partnership": { + "title": "Partnership", + "description": "We create the best results through close communication and collaboration with customers." + } + }, + "cta": { + "title": "We'll Grow Together", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + } + }, + "footer": { + "description": "Digital solution specialist leading innovation", + "links": { + "title": "Quick Links" + }, + "contact": { + "title": "Contact", + "email": "info@smartsoltech.co.kr", + "phone": "+82-2-1234-5678", + "address": "123 Teheran-ro, Gangnam-gu, Seoul" + }, + "copyright": "© 2024 SmartSolTech. All rights reserved." + }, + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "toggle": "Toggle Theme" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша" + }, + "common": { + "loading": "Loading...", + "error": "Error occurred", + "success": "Success", + "view_more": "View More", + "back": "Back", + "next": "Next", + "previous": "Previous", + "view_details": "View Details" + }, + "meta": { + "description": "SmartSolTech - Innovative web development, mobile app development, UI/UX design services", + "keywords": "web development, mobile apps, UI/UX design, Korea", + "title": "SmartSolTech" + }, + "nav": { + "home": "Home", + "about": "About", + "services": "Services", + "portfolio": "Portfolio", + "calculator": "Calculator" + }, + "admin": { + "login": "Admin Panel Login", + "dashboard": "Dashboard", + "title": "SmartSolTech Admin" + }, + "company": { + "name": "SmartSolTech", + "description": "Digital solution specialist leading innovation", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678" + }, + "errors": { + "page_not_found": "Page not found", + "error_occurred": "Error occurred", + "title": "Error - SmartSolTech", + "default_title": "An Error Occurred", + "default_message": "A problem occurred while processing the request.", + "back_home": "Back to Home", + "go_back": "Go Back", + "need_help": "Need Help?", + "help_message": "If the problem persists, please contact us anytime.", + "contact_support": "Contact Support" + }, + "pages": { + "home": "Home page", + "about": "About us", + "services": "Services", + "portfolio": "Portfolio", + "contact": "Contact", + "calculator": "Calculator" + }, + "portfolio_page": { + "title": "우리의 포트폴리오", + "subtitle": "혁신적인 프로젝트와 창의적인 솔루션들을 만나보세요", + "categories": { + "all": "전체", + "web-development": "웹 개발", + "mobile-app": "모바일 앱", + "ui-ux-design": "UI/UX 디자인", + "branding": "브랜딩", + "marketing": "디지털 마케팅" + }, + "buttons": { + "details": "자세히 보기", + "projectDetails": "프로젝트 상세보기", + "loadMore": "더 많은 프로젝트 보기", + "contact": "프로젝트 문의하기", + "calculate": "비용 계산하기" + }, + "empty": { + "title": "아직 포트폴리오가 없습니다", + "subtitle": "곧 멋진 프로젝트들을 공개할 예정입니다!" + }, + "cta": { + "title": "다음 프로젝트의 주인공이 되어보세요", + "subtitle": "우리와 함께 혁신적인 디지털 솔루션을 만들어보세요" + }, + "labels": { + "featured": "추천", + "views": "조회수", + "likes": "좋아요" + } + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251019203653.json b/.history/locales/ru_20251019203653.json new file mode 100644 index 0000000..56261d2 --- /dev/null +++ b/.history/locales/ru_20251019203653.json @@ -0,0 +1,318 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "hero.title.solutions" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "hero.cta.start", + "portfolio": "hero.cta.portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020044247.json b/.history/locales/ru_20251020044247.json new file mode 100644 index 0000000..f75e8b5 --- /dev/null +++ b/.history/locales/ru_20251020044247.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "hero.title.solutions" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "hero.cta.start", + "portfolio": "hero.cta.portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020044352.json b/.history/locales/ru_20251020044352.json new file mode 100644 index 0000000..f75e8b5 --- /dev/null +++ b/.history/locales/ru_20251020044352.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "hero.title.solutions" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "hero.cta.start", + "portfolio": "hero.cta.portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020225647.json b/.history/locales/ru_20251020225647.json new file mode 100644 index 0000000..7d907d3 --- /dev/null +++ b/.history/locales/ru_20251020225647.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "hero.cta.start", + "portfolio": "hero.cta.portfolio" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230125.json b/.history/locales/ru_20251020230125.json new file mode 100644 index 0000000..5328610 --- /dev/null +++ b/.history/locales/ru_20251020230125.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "services.title.our", + "services": "services.title.services" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230133.json b/.history/locales/ru_20251020230133.json new file mode 100644 index 0000000..c636666 --- /dev/null +++ b/.history/locales/ru_20251020230133.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "services.subtitle", + "web": { + "title": "services.web.title", + "description": "services.web.description", + "price": "services.web.price" + }, + "mobile": { + "title": "services.mobile.title", + "description": "services.mobile.description", + "price": "services.mobile.price" + }, + "design": { + "title": "services.design.title", + "description": "services.design.description", + "price": "services.design.price" + }, + "marketing": { + "title": "services.marketing.title", + "description": "services.marketing.description", + "price": "services.marketing.price" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230144.json b/.history/locales/ru_20251020230144.json new file mode 100644 index 0000000..5facc8d --- /dev/null +++ b/.history/locales/ru_20251020230144.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "portfolio.title.recent", + "projects": "portfolio.title.projects" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230151.json b/.history/locales/ru_20251020230151.json new file mode 100644 index 0000000..0e75ac0 --- /dev/null +++ b/.history/locales/ru_20251020230151.json @@ -0,0 +1,349 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "portfolio.subtitle" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230159.json b/.history/locales/ru_20251020230159.json new file mode 100644 index 0000000..844651b --- /dev/null +++ b/.history/locales/ru_20251020230159.json @@ -0,0 +1,354 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "contact.form.title", + "service": { + "select": "contact.form.service.select", + "web": "contact.form.service.web", + "mobile": "contact.form.service.mobile", + "design": "contact.form.service.design", + "branding": "contact.form.service.branding", + "consulting": "contact.form.service.consulting", + "other": "contact.form.service.other" + }, + "success": "contact.form.success", + "error": "contact.form.error" + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230209.json b/.history/locales/ru_20251020230209.json new file mode 100644 index 0000000..1420f03 --- /dev/null +++ b/.history/locales/ru_20251020230209.json @@ -0,0 +1,354 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "contact.cta.ready", + "start": "contact.cta.start", + "question": "contact.cta.question", + "subtitle": "contact.cta.subtitle" + }, + "phone": { + "title": "contact.phone.title", + "number": "contact.phone.number" + }, + "email": { + "title": "contact.email.title", + "address": "contact.email.address" + }, + "telegram": { + "title": "contact.telegram.title", + "subtitle": "contact.telegram.subtitle" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230219.json b/.history/locales/ru_20251020230219.json new file mode 100644 index 0000000..0fbd309 --- /dev/null +++ b/.history/locales/ru_20251020230219.json @@ -0,0 +1,354 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "common.view_details" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230226.json b/.history/locales/ru_20251020230226.json new file mode 100644 index 0000000..045275a --- /dev/null +++ b/.history/locales/ru_20251020230226.json @@ -0,0 +1,354 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "meta.description", + "keywords": "meta.keywords", + "title": "meta.title" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230234.json b/.history/locales/ru_20251020230234.json new file mode 100644 index 0000000..fce0c92 --- /dev/null +++ b/.history/locales/ru_20251020230234.json @@ -0,0 +1,354 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230247.json b/.history/locales/ru_20251020230247.json new file mode 100644 index 0000000..fce0c92 --- /dev/null +++ b/.history/locales/ru_20251020230247.json @@ -0,0 +1,354 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "language.ko" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230428.json b/.history/locales/ru_20251020230428.json new file mode 100644 index 0000000..c1dd95d --- /dev/null +++ b/.history/locales/ru_20251020230428.json @@ -0,0 +1,357 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251020230440.json b/.history/locales/ru_20251020230440.json new file mode 100644 index 0000000..c1dd95d --- /dev/null +++ b/.history/locales/ru_20251020230440.json @@ -0,0 +1,357 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021040800.json b/.history/locales/ru_20251021040800.json new file mode 100644 index 0000000..486afea --- /dev/null +++ b/.history/locales/ru_20251021040800.json @@ -0,0 +1,357 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаунт для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021175542.json b/.history/locales/ru_20251021175542.json new file mode 100644 index 0000000..ef7b41d --- /dev/null +++ b/.history/locales/ru_20251021175542.json @@ -0,0 +1,395 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021183217.json b/.history/locales/ru_20251021183217.json new file mode 100644 index 0000000..ef7b41d --- /dev/null +++ b/.history/locales/ru_20251021183217.json @@ -0,0 +1,395 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021183706.json b/.history/locales/ru_20251021183706.json new file mode 100644 index 0000000..78efed5 --- /dev/null +++ b/.history/locales/ru_20251021183706.json @@ -0,0 +1,402 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + }, + "portfolio": { + "default": { + "ecommerce": "Электронная коммерция", + "title": "Интернет-магазин", + "description": "Современная платформа электронной коммерции с интуитивным интерфейсом" + } + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021183802.json b/.history/locales/ru_20251021183802.json new file mode 100644 index 0000000..b28e6c4 --- /dev/null +++ b/.history/locales/ru_20251021183802.json @@ -0,0 +1,395 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184019.json b/.history/locales/ru_20251021184019.json new file mode 100644 index 0000000..788e599 --- /dev/null +++ b/.history/locales/ru_20251021184019.json @@ -0,0 +1,403 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184027.json b/.history/locales/ru_20251021184027.json new file mode 100644 index 0000000..788e599 --- /dev/null +++ b/.history/locales/ru_20251021184027.json @@ -0,0 +1,403 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184143.json b/.history/locales/ru_20251021184143.json new file mode 100644 index 0000000..f60ff92 --- /dev/null +++ b/.history/locales/ru_20251021184143.json @@ -0,0 +1,408 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184308.json b/.history/locales/ru_20251021184308.json new file mode 100644 index 0000000..f60ff92 --- /dev/null +++ b/.history/locales/ru_20251021184308.json @@ -0,0 +1,408 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184331.json b/.history/locales/ru_20251021184331.json new file mode 100644 index 0000000..9634358 --- /dev/null +++ b/.history/locales/ru_20251021184331.json @@ -0,0 +1,430 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184333.json b/.history/locales/ru_20251021184333.json new file mode 100644 index 0000000..9634358 --- /dev/null +++ b/.history/locales/ru_20251021184333.json @@ -0,0 +1,430 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184528.json b/.history/locales/ru_20251021184528.json new file mode 100644 index 0000000..c4e67e7 --- /dev/null +++ b/.history/locales/ru_20251021184528.json @@ -0,0 +1,437 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021184547.json b/.history/locales/ru_20251021184547.json new file mode 100644 index 0000000..c4e67e7 --- /dev/null +++ b/.history/locales/ru_20251021184547.json @@ -0,0 +1,437 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms" + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021210015.json b/.history/locales/ru_20251021210015.json new file mode 100644 index 0000000..3608079 --- /dev/null +++ b/.history/locales/ru_20251021210015.json @@ -0,0 +1,484 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_project": "View Project", + "categories": { + "all": "All", + "web": "Web Development", + "mobile": "Mobile Apps", + "uiux": "UI/UX Design" + }, + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021210040.json b/.history/locales/ru_20251021210040.json new file mode 100644 index 0000000..753c566 --- /dev/null +++ b/.history/locales/ru_20251021210040.json @@ -0,0 +1,485 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_project": "View Project", + "categories": { + "all": "Все", + "web": "Веб-разработка", + "mobile": "Мобильные приложения", + "uiux": "UI/UX дизайн" + }, + "project_details": "Детали проекта", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021210347.json b/.history/locales/ru_20251021210347.json new file mode 100644 index 0000000..34141a4 --- /dev/null +++ b/.history/locales/ru_20251021210347.json @@ -0,0 +1,485 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + } + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "title_highlight": "Услуги", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + }, + "view_all": "Посмотреть все услуги", + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "title_highlight": "Проекты", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_project": "View Project", + "categories": { + "all": "Все", + "web": "Веб-разработка", + "mobile": "Мобильные приложения", + "uiux": "UI/UX дизайн" + }, + "project_details": "Детали проекта", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + } + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию", + "form": { + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "message": "Кратко опишите ваш проект", + "submit": "Подать заявку на консультацию", + "title": "Заявка на бесплатную консультацию", + "service": { + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + } + }, + "about": { + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "values": { + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + } + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио", + "subtitle": "Turn your ideas into reality", + "button": "Contact Us" + }, + "meta": { + "title": "About Us", + "description": "SmartSolTech is a professional development company that supports customer business growth with innovative technology" + }, + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + } + }, + "footer": { + "company": { + "description": "footer.company.description" + }, + "description": "Специалист по цифровым решениям, ведущий инновации", + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "links": { + "title": "footer.links.title", + "privacy": "Privacy Policy", + "terms": "Terms of Service", + "sitemap": "Sitemap" + }, + "contact": { + "title": "footer.contact.title", + "email": "footer.contact.email", + "phone": "footer.contact.phone", + "address": "footer.contact.address" + }, + "copyright": "footer.copyright", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Follow Us" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech", + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard": "Панель управления", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "title": "SmartSolTech Admin", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "full_name": "SmartSolTech - Инновационные технологические решения", + "description": "Специалист по цифровым решениям, ведущий инновации", + "tagline": "Будущее начинается здесь", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "contact_us": "Свяжитесь с нами", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + } +} \ No newline at end of file diff --git a/.history/locales/ru_20251021210903.json b/.history/locales/ru_20251021210903.json new file mode 100644 index 0000000..c8f4b9f --- /dev/null +++ b/.history/locales/ru_20251021210903.json @@ -0,0 +1,492 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + }, + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио" + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "view_all": "Посмотреть все услуги", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + }, + "title_highlight": "Услуги", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "categories": { + "all": "Все", + "web": "Веб-разработка", + "mobile": "Мобильные приложения", + "uiux": "UI/UX дизайн" + }, + "project_details": "Детали проекта", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + }, + "title_highlight": "Проекты", + "view_project": "View Project" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "form": { + "title": "Заявка на проект", + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "message": "Кратко опишите ваш проект", + "submit": "Отправить заявку", + "success": "Заявка успешно отправлена", + "error": "Произошла ошибка при отправке заявки", + "service": { + "title": "Интересующая услуга", + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + } + }, + "info": { + "title": "Контактная информация" + }, + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-10-1234-5678" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.kr" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Мгновенный ответ доступен" + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + }, + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию" + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "button": "Связаться с нами", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + }, + "meta": { + "title": "О нас", + "description": "SmartSolTech - это профессиональная компания по разработке, которая поддерживает рост бизнеса клиентов с помощью инновационных технологий" + }, + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + } + }, + "footer": { + "description": "Специалист по цифровым решениям, ведущий инновации", + "links": { + "title": "footer.links.title", + "privacy": "Политика конфиденциальности", + "terms": "Условия обслуживания", + "sitemap": "Карта сайта" + }, + "contact": { + "title": "Контакты", + "email": "E-mail", + "phone": "Телефон", + "address": "Адрес" + }, + "copyright": "© 2024 SmartSolTech. Все права защищены.", + "company": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса" + }, + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Подписывайтесь на нас" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "dashboard": "Панель управления", + "title": "SmartSolTech Admin", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Специалист по цифровым решениям, ведущий инновации", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Инновационные технологические решения", + "tagline": "Будущее начинается здесь", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ru_20251021210932.json b/.history/locales/ru_20251021210932.json new file mode 100644 index 0000000..75b1b2d --- /dev/null +++ b/.history/locales/ru_20251021210932.json @@ -0,0 +1,499 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + }, + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио" + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "view_all": "Посмотреть все услуги", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + }, + "title_highlight": "Услуги", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "categories": { + "all": "Все", + "web": "Веб-разработка", + "mobile": "Мобильные приложения", + "uiux": "UI/UX дизайн" + }, + "project_details": "Детали проекта", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + }, + "title_highlight": "Проекты", + "view_project": "View Project" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "form": { + "title": "Заявка на проект", + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "message": "Кратко опишите ваш проект", + "submit": "Отправить заявку", + "success": "Заявка успешно отправлена", + "error": "Произошла ошибка при отправке заявки", + "service": { + "title": "Интересующая услуга", + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + } + }, + "info": { + "title": "Контактная информация" + }, + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-2-1234-5678", + "hours": "Пн-Пт 9:00-18:00" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.co.kr", + "response": "Ответ в течение 24 часов" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Для быстрого ответа" + }, + "address": { + "title": "Адрес офиса", + "line1": "Теheran-ro 123, Gangnam-gu", + "line2": "Сеул, Южная Корея" + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + }, + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию" + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "button": "Связаться с нами", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + }, + "meta": { + "title": "О нас", + "description": "SmartSolTech - это профессиональная компания по разработке, которая поддерживает рост бизнеса клиентов с помощью инновационных технологий" + }, + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + } + }, + "footer": { + "description": "Специалист по цифровым решениям, ведущий инновации", + "links": { + "title": "footer.links.title", + "privacy": "Политика конфиденциальности", + "terms": "Условия обслуживания", + "sitemap": "Карта сайта" + }, + "contact": { + "title": "Контакты", + "email": "E-mail", + "phone": "Телефон", + "address": "Адрес" + }, + "copyright": "© 2024 SmartSolTech. Все права защищены.", + "company": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса" + }, + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Подписывайтесь на нас" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "dashboard": "Панель управления", + "title": "SmartSolTech Admin", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Специалист по цифровым решениям, ведущий инновации", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Инновационные технологические решения", + "tagline": "Будущее начинается здесь", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ru_20251021211322.json b/.history/locales/ru_20251021211322.json new file mode 100644 index 0000000..ad76eca --- /dev/null +++ b/.history/locales/ru_20251021211322.json @@ -0,0 +1,531 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + }, + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио" + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "view_all": "Посмотреть все услуги", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + }, + "title_highlight": "Услуги", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "categories": { + "all": "Все", + "web": "Веб-разработка", + "mobile": "Мобильные приложения", + "uiux": "UI/UX дизайн" + }, + "project_details": "Детали проекта", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + }, + "title_highlight": "Проекты", + "view_project": "View Project" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "form": { + "title": "Заявка на проект", + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "message": "Кратко опишите ваш проект", + "submit": "Отправить заявку", + "success": "Заявка успешно отправлена", + "error": "Произошла ошибка при отправке заявки", + "service": { + "title": "Интересующая услуга", + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + } + }, + "info": { + "title": "Контактная информация" + }, + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-2-1234-5678", + "hours": "Пн-Пт 9:00-18:00" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.co.kr", + "response": "Ответ в течение 24 часов" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Для быстрого ответа" + }, + "address": { + "title": "Адрес офиса", + "line1": "Теheran-ro 123, Gangnam-gu", + "line2": "Сеул, Южная Корея" + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + }, + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию" + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "button": "Связаться с нами", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + }, + "meta": { + "title": "О нас", + "description": "SmartSolTech - это профессиональная компания по разработке, которая поддерживает рост бизнеса клиентов с помощью инновационных технологий" + }, + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + } + }, + "footer": { + "description": "Специалист по цифровым решениям, ведущий инновации", + "links": { + "title": "footer.links.title", + "privacy": "Политика конфиденциальности", + "terms": "Условия обслуживания", + "sitemap": "Карта сайта" + }, + "contact": { + "title": "Контакты", + "email": "E-mail", + "phone": "Телефон", + "address": "Адрес" + }, + "copyright": "© 2024 SmartSolTech. Все права защищены.", + "company": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса" + }, + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Подписывайтесь на нас" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "dashboard": "Панель управления", + "title": "SmartSolTech Admin", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Специалист по цифровым решениям, ведущий инновации", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Инновационные технологические решения", + "tagline": "Будущее начинается здесь", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + }, + "portfolio_page": { + "title": "Наше портфолио", + "subtitle": "Знакомьтесь с инновационными проектами и креативными решениями", + "categories": { + "all": "Все", + "web-development": "Веб-разработка", + "mobile-app": "Мобильные приложения", + "ui-ux-design": "UI/UX дизайн", + "branding": "Брендинг", + "marketing": "Цифровой маркетинг" + }, + "buttons": { + "details": "Подробнее", + "projectDetails": "Подробности проекта", + "loadMore": "Больше проектов", + "contact": "Запросить проект", + "calculate": "Рассчитать стоимость" + }, + "empty": { + "title": "Портфолио пока пусто", + "subtitle": "Скоро мы представим замечательные проекты!" + }, + "cta": { + "title": "Станьте героем следующего проекта", + "subtitle": "Создайте с нами инновационное цифровое решение" + }, + "labels": { + "featured": "РЕКОМЕНДУЕМОЕ", + "views": "просмотров", + "likes": "лайков" + } + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/locales/ru_20251021211513.json b/.history/locales/ru_20251021211513.json new file mode 100644 index 0000000..ad76eca --- /dev/null +++ b/.history/locales/ru_20251021211513.json @@ -0,0 +1,531 @@ +{ + "navigation": { + "home": "Главная", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор", + "admin": "Админ", + "home - SmartSolTech": "Главная - SmartSolTech" + }, + "hero": { + "title": { + "smart": "SmartSolTech", + "solutions": "Future begins here" + }, + "subtitle": "Решения", + "description": "Инновационная веб-разработка, мобильные приложения, UI/UX дизайн для цифровой трансформации вашего бизнеса", + "cta": { + "start": "Начать проект", + "portfolio": "Посмотреть портфолио" + }, + "cta_primary": "Начать проект", + "cta_secondary": "Посмотреть портфолио" + }, + "services": { + "title": { + "our": "Наши", + "services": "Услуги" + }, + "subtitle": "Цифровые решения с использованием передовых технологий и творческих идей", + "description": "Цифровые решения с использованием передовых технологий и творческих идей", + "view_all": "Посмотреть все услуги", + "web": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "от $5,000" + }, + "mobile": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "от $8,000" + }, + "design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "от $3,000" + }, + "marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "от $2,000" + }, + "meta": { + "title": "Услуги", + "description": "Ознакомьтесь с профессиональными услугами SmartSolTech. Веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг и другие технологические решения.", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, цифровой маркетинг, технологические решения, SmartSolTech" + }, + "hero": { + "title": "Наши", + "title_highlight": "Услуги", + "subtitle": "Поддерживаем рост бизнеса с помощью инновационных технологий" + }, + "cards": { + "starting_price": "Стартовая цена", + "consultation": "консультация", + "contact": "Связаться", + "calculate_cost": "Рассчитать стоимость", + "popular": "Популярно", + "coming_soon": "Услуги готовятся", + "coming_soon_desc": "Скоро мы предложим разнообразные услуги!" + }, + "process": { + "title": "Процесс реализации проекта", + "subtitle": "Мы ведем проекты с помощью систематических и профессиональных процессов", + "consultation": { + "title": "Консультация и планирование", + "description": "Точно понимаем требования клиента и" + } + }, + "title_highlight": "Услуги", + "web_development": { + "title": "Веб-разработка", + "description": "Современные и адаптивные веб-сайты и веб-приложения", + "price": "$5,000~" + }, + "mobile_app": { + "title": "Мобильные приложения", + "description": "Нативные и кроссплатформенные приложения для iOS и Android", + "price": "$8,000~" + }, + "ui_ux_design": { + "title": "UI/UX дизайн", + "description": "Ориентированный на пользователя интуитивный и красивый дизайн интерфейса", + "price": "$3,000~" + }, + "digital_marketing": { + "title": "Цифровой маркетинг", + "description": "Цифровой маркетинг через SEO, социальные сети, онлайн-рекламу", + "price": "$2,000~" + } + }, + "portfolio": { + "title": { + "recent": "Последние", + "projects": "Проекты", + "our": "Our", + "portfolio": "Portfolio" + }, + "subtitle": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "description": "Ознакомьтесь с проектами, выполненными для успеха клиентов", + "view_details": "Подробнее", + "view_all": "Посмотреть все портфолио", + "categories": { + "all": "Все", + "web": "Веб-разработка", + "mobile": "Мобильные приложения", + "uiux": "UI/UX дизайн" + }, + "project_details": "Детали проекта", + "default": { + "ecommerce": "Электронная коммерция", + "title": "Платформа электронной коммерции", + "description": "Современное решение для онлайн-торговли с интуитивным интерфейсом" + }, + "meta": { + "title": "Портфолио", + "description": "Ознакомьтесь с разнообразными проектами и историями успеха SmartSolTech. Портфолио веб-разработки, мобильных приложений, UI/UX дизайна.", + "keywords": "портфолио, веб-разработка, мобильные приложения, UI/UX дизайн, проекты, SmartSolTech", + "og_title": "Портфолио - SmartSolTech", + "og_description": "Разнообразные проекты и истории успеха SmartSolTech" + }, + "title_highlight": "Проекты", + "view_project": "View Project" + }, + "calculator": { + "title": "Калькулятор Стоимости Проекта", + "subtitle": "Выберите нужные услуги и требования для получения точной оценки стоимости в режиме реального времени", + "meta": { + "title": "Калькулятор стоимости проекта", + "description": "Рассчитайте стоимость вашего проекта веб-разработки, мобильного приложения или дизайна с помощью нашего интерактивного калькулятора" + }, + "cta": { + "title": "Узнайте стоимость вашего проекта", + "subtitle": "Выберите необходимые услуги и требования, и мы рассчитаем стоимость в режиме реального времени", + "button": "Использовать калькулятор стоимости" + }, + "step1": { + "title": "Шаг 1: Выбор услуг", + "subtitle": "Выберите необходимые услуги (можно выбрать несколько)" + }, + "step2": { + "title": "Шаг 2: Детали проекта", + "subtitle": "Выберите сложность проекта и сроки" + }, + "complexity": { + "title": "Сложность проекта", + "simple": "Простой", + "simple_desc": "Базовый функционал, стандартный дизайн", + "medium": "Средний", + "medium_desc": "Дополнительные функции, кастомный дизайн", + "complex": "Сложный", + "complex_desc": "Расширенный функционал, интеграции" + }, + "timeline": { + "title": "Временные рамки", + "standard": "Стандартные", + "standard_desc": "Обычные сроки разработки", + "rush": "Срочно", + "rush_desc": "Ускоренная разработка (+50%)", + "extended": "Расширенные", + "extended_desc": "Длительная разработка (-20%)" + }, + "result": { + "title": "Результат расчета", + "subtitle": "Вот ваша предварительная оценка стоимости проекта", + "estimated_price": "Предварительная стоимость", + "price_note": "* Окончательная стоимость может варьироваться в зависимости от деталей проекта", + "summary": "Сводка проекта", + "selected_services": "Выбранные услуги", + "complexity": "Сложность", + "timeline": "Временные рамки", + "get_quote": "Получить точное предложение", + "recalculate": "Пересчитать", + "contact_note": "Свяжитесь с нами для получения точного предложения и обсуждения деталей проекта" + }, + "next_step": "Следующий шаг", + "prev_step": "Назад", + "calculate": "Рассчитать" + }, + "contact": { + "hero": { + "title": "Свяжитесь с нами", + "subtitle": "Мы здесь, чтобы помочь воплотить ваши идеи в жизнь" + }, + "ready_title": "Готовы начать свой проект?", + "ready_description": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "form": { + "title": "Заявка на проект", + "name": "Имя", + "email": "Электронная почта", + "phone": "Телефон", + "message": "Кратко опишите ваш проект", + "submit": "Отправить заявку", + "success": "Заявка успешно отправлена", + "error": "Произошла ошибка при отправке заявки", + "service": { + "title": "Интересующая услуга", + "select": "Выберите интересующую услугу", + "web": "Веб-разработка", + "mobile": "Мобильное приложение", + "design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + } + }, + "info": { + "title": "Контактная информация" + }, + "service_interest": "Интересующая услуга", + "service_options": { + "select": "Выберите интересующую услугу", + "web_development": "Веб-разработка", + "mobile_app": "Мобильное приложение", + "ui_ux_design": "UI/UX дизайн", + "branding": "Брендинг", + "consulting": "Консалтинг", + "other": "Другое" + }, + "success": "Спасибо! Мы свяжемся с вами в ближайшее время.", + "error": "Произошла ошибка. Попробуйте снова." + }, + "phone": { + "title": "Телефонная консультация", + "number": "+82-2-1234-5678", + "hours": "Пн-Пт 9:00-18:00" + }, + "email": { + "title": "Электронная почта", + "address": "info@smartsoltech.co.kr", + "response": "Ответ в течение 24 часов" + }, + "telegram": { + "title": "Telegram", + "subtitle": "Для быстрого ответа" + }, + "address": { + "title": "Адрес офиса", + "line1": "Теheran-ro 123, Gangnam-gu", + "line2": "Сеул, Южная Корея" + }, + "cta": { + "ready": "Готовы начать", + "start": "свой проект", + "question": "?", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения." + }, + "meta": { + "title": "Contact", + "description": "Contact us anytime for project inquiries or consultation" + }, + "phone_consultation": "Телефонная консультация", + "email_inquiry": "Запрос по электронной почте", + "telegram_chat": "Чат в Telegram", + "instant_response": "Мгновенный ответ доступен", + "free_consultation": "Заявка на бесплатную консультацию" + }, + "about": { + "hero": { + "title": "About SmartSolTech", + "subtitle": "Creating the future with innovation and technology" + }, + "company": { + "title": "Company Information", + "description1": "SmartSolTech is a technology company established in 2020, recognized for expertise in web development, mobile app development, and UI/UX design.", + "description2": "We accurately understand customer needs and provide innovative solutions using the latest technology." + }, + "stats": { + "projects": "Completed Projects", + "experience": "Years Experience", + "clients": "Satisfied Customers" + }, + "mission": { + "title": "Our Mission", + "description": "Our mission is to support customer business growth through technology and lead digital innovation." + }, + "values": { + "innovation": { + "title": "Инновации", + "description": "Мы предоставляем инновационные решения через непрерывные исследования и внедрение передовых технологий." + }, + "quality": { + "title": "Качество", + "description": "Мы поддерживаем высокие стандарты качества и предоставляем высококачественные продукты, которыми клиенты могут быть довольны." + }, + "partnership": { + "title": "Сотрудничество", + "description": "Мы создаем лучшие результаты через тесное общение и сотрудничество с клиентами." + }, + "title": "Основные", + "title_highlight": "Ценности", + "description": "Основные ценности, которых придерживается SmartSolTech", + "collaboration": { + "title": "Collaboration", + "description": "We create the best results through close communication and collaboration with customers." + }, + "growth": { + "title": "Рост", + "description": "Мы растем вместе с клиентами и стремимся к непрерывному обучению и развитию." + } + }, + "cta": { + "title": "Станьте партнером для совместного успеха", + "subtitle": "Превратите свои идеи в реальность. Эксперты предоставят лучшие решения.", + "button": "Связаться с нами", + "description": "Выведите свой бизнес на следующий уровень с SmartSolTech", + "partnership": "Запрос о партнерстве", + "portfolio": "Посмотреть портфолио" + }, + "meta": { + "title": "О нас", + "description": "SmartSolTech - это профессиональная компания по разработке, которая поддерживает рост бизнеса клиентов с помощью инновационных технологий" + }, + "hero_title": "О", + "hero_highlight": "SmartSolTech", + "hero_description": "Специалист по цифровым решениям, ведущий к успеху клиентов с помощью инновационных технологий", + "overview": { + "title": "Создавая будущее с инновациями и креативностью", + "description_1": "SmartSolTech - это специалист по цифровым решениям, основанный в 2020 году, поддерживающий успех клиентского бизнеса с помощью инновационных технологий и творческих идей в области веб-разработки, мобильных приложений и UI/UX дизайна.", + "description_2": "Мы не просто предоставляем технологии, но понимаем цели клиентов и предлагаем оптимальные решения, чтобы стать партнерами, растущими вместе.", + "stats": { + "projects": "100+", + "projects_label": "Завершенные проекты", + "clients": "50+", + "clients_label": "Довольные клиенты", + "experience": "4 года", + "experience_label": "Опыт в отрасли" + }, + "mission": "Наша миссия", + "mission_text": "Помощь всем предприятиям в достижении успеха в цифровую эпоху с помощью технологий", + "vision": "Наше видение", + "vision_text": "Рост как глобальной компании цифровых решений, представляющей Корею, для ведения цифровых инноваций для клиентов по всему миру" + }, + "team": { + "title": "Наша", + "title_highlight": "Команда", + "description": "Представляем команду SmartSolTech с экспертизой и страстью" + }, + "tech_stack": { + "title": "Технологический", + "title_highlight": "Стек", + "description": "Мы предоставляем лучшие решения с передовыми технологиями и проверенными инструментами", + "frontend": "Frontend", + "backend": "Backend", + "mobile": "Мобильные" + } + }, + "footer": { + "description": "Специалист по цифровым решениям, ведущий инновации", + "links": { + "title": "footer.links.title", + "privacy": "Политика конфиденциальности", + "terms": "Условия обслуживания", + "sitemap": "Карта сайта" + }, + "contact": { + "title": "Контакты", + "email": "E-mail", + "phone": "Телефон", + "address": "Адрес" + }, + "copyright": "© 2024 SmartSolTech. Все права защищены.", + "company": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса" + }, + "quick_links": "Быстрые ссылки", + "services": "Услуги", + "contact_info": "Контактная информация", + "follow_us": "Подписывайтесь", + "rights": "Все права защищены.", + "privacy": "footer.privacy", + "terms": "footer.terms", + "social": { + "follow": "Подписывайтесь на нас" + } + }, + "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "toggle": "Переключить тему" + }, + "language": { + "english": "English", + "korean": "한국어", + "russian": "Русский", + "kazakh": "Қазақша", + "ko": "한국어", + "en": "English", + "ru": "Русский", + "kk": "Қазақша" + }, + "common": { + "loading": "Загрузка...", + "error": "Произошла ошибка", + "success": "Успешно", + "view_more": "Посмотреть еще", + "back": "Назад", + "next": "Далее", + "previous": "Предыдущий", + "view_details": "Подробнее" + }, + "meta": { + "description": "SmartSolTech - Инновационные технологические решения для вашего бизнеса", + "keywords": "веб-разработка, мобильные приложения, UI/UX дизайн, SmartSolTech", + "title": "SmartSolTech - Инновационные технологические решения" + }, + "nav": { + "home": "nav.home", + "about": "nav.about", + "services": "nav.services", + "portfolio": "nav.portfolio", + "calculator": "nav.calculator" + }, + "admin": { + "login": "Вход в админ панель", + "dashboard": "Панель управления", + "title": "SmartSolTech Admin", + "login_title": "Вход в админ панель", + "login_subtitle": "Войдите в свой аккаunt для управления сайтом", + "login_button": "Войти", + "email": "Email", + "password": "Пароль", + "email_placeholder": "admin@smartsoltech.com", + "password_placeholder": "Введите пароль", + "back_to_site": "Вернуться на сайт", + "dashboard_subtitle": "Обзор основных показателей сайта", + "portfolio": "Портфолио", + "services": "Услуги", + "contacts": "Сообщения", + "settings": "Настройки", + "users": "Пользователи", + "logout": "Выход", + "view_site": "Посмотреть сайт", + "view_all": "Посмотреть всё", + "portfolio_projects": "Проекты", + "contact_messages": "Сообщения", + "recent_portfolio": "Последние проекты", + "recent_contacts": "Последние сообщения", + "no_recent_portfolio": "Нет недавних проектов", + "no_recent_contacts": "Нет недавних сообщений", + "quick_actions": "Быстрые действия", + "add_portfolio": "Добавить проект", + "add_service": "Добавить услугу", + "site_settings": "Настройки сайта", + "banner_editor": "Редактор Баннеров", + "current_banner": "Текущий баннер", + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио" + } + }, + "company": { + "name": "SmartSolTech", + "description": "Специалист по цифровым решениям, ведущий инновации", + "email": "info@smartsoltech.kr", + "phone": "+82-10-1234-5678", + "full_name": "SmartSolTech - Инновационные технологические решения", + "tagline": "Будущее начинается здесь", + "address": "Seoul, South Korea", + "social": { + "telegram": "@smartsoltech" + } + }, + "errors": { + "page_not_found": "Страница не найдена", + "error_occurred": "Произошла ошибка", + "title": "Произошла ошибка - SmartSolTech", + "default_title": "Произошла ошибка", + "default_message": "При обработке запроса возникла проблема.", + "back_home": "Вернуться на главную", + "go_back": "Назад", + "need_help": "Нужна помощь?", + "help_message": "Если проблема продолжается, свяжитесь с нами в любое время.", + "contact_support": "Обратиться в поддержку", + "contact_us": "Свяжитесь с нами" + }, + "pages": { + "home": "Главная страница", + "about": "О нас", + "services": "Услуги", + "portfolio": "Портфолио", + "contact": "Контакты", + "calculator": "Калькулятор" + }, + "portfolio_page": { + "title": "Наше портфолио", + "subtitle": "Знакомьтесь с инновационными проектами и креативными решениями", + "categories": { + "all": "Все", + "web-development": "Веб-разработка", + "mobile-app": "Мобильные приложения", + "ui-ux-design": "UI/UX дизайн", + "branding": "Брендинг", + "marketing": "Цифровой маркетинг" + }, + "buttons": { + "details": "Подробнее", + "projectDetails": "Подробности проекта", + "loadMore": "Больше проектов", + "contact": "Запросить проект", + "calculate": "Рассчитать стоимость" + }, + "empty": { + "title": "Портфолио пока пусто", + "subtitle": "Скоро мы представим замечательные проекты!" + }, + "cta": { + "title": "Станьте героем следующего проекта", + "subtitle": "Создайте с нами инновационное цифровое решение" + }, + "labels": { + "featured": "РЕКОМЕНДУЕМОЕ", + "views": "просмотров", + "likes": "лайков" + } + }, + "undefined - SmartSolTech": "undefined - SmartSolTech" +} \ No newline at end of file diff --git a/.history/middleware/auth_20251019202041.js b/.history/middleware/auth_20251019202041.js new file mode 100644 index 0000000..6a338bd --- /dev/null +++ b/.history/middleware/auth_20251019202041.js @@ -0,0 +1,154 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models'); + +/** + * Authentication middleware + * Verifies JWT token and attaches user to request + */ +const authenticateToken = async (req, res, next) => { + try { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN + + if (!token) { + return res.status(401).json({ + success: false, + message: 'Access token required' + }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findById(decoded.userId).select('-password'); + + if (!user || !user.isActive) { + return res.status(401).json({ + success: false, + message: 'Invalid or inactive user' + }); + } + + req.user = user; + next(); + } catch (error) { + console.error('Token verification error:', error); + return res.status(403).json({ + success: false, + message: 'Invalid token' + }); + } +}; + +/** + * Session-based authentication middleware + * For web pages using sessions + */ +const authenticateSession = async (req, res, next) => { + try { + if (!req.session.userId) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + const user = await User.findById(req.session.userId).select('-password'); + + if (!user || !user.isActive) { + req.session.destroy(); + req.flash('error', '유효하지 않은 사용자입니다.'); + return res.redirect('/auth/login'); + } + + req.user = user; + res.locals.user = user; + next(); + } catch (error) { + console.error('Session authentication error:', error); + req.session.destroy(); + req.flash('error', '인증 오류가 발생했습니다.'); + return res.redirect('/auth/login'); + } +}; + +/** + * Admin role middleware + * Requires user to be authenticated and have admin role + */ +const requireAdmin = (req, res, next) => { + if (!req.user) { + return res.status(401).json({ + success: false, + message: 'Authentication required' + }); + } + + if (req.user.role !== 'admin') { + return res.status(403).json({ + success: false, + message: 'Admin access required' + }); + } + + next(); +}; + +/** + * Admin session middleware for web pages + */ +const requireAdminSession = (req, res, next) => { + if (!req.user) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + if (req.user.role !== 'admin') { + req.flash('error', '관리자 권한이 필요합니다.'); + return res.redirect('/'); + } + + next(); +}; + +/** + * Optional authentication middleware + * Attaches user if token exists but doesn't require it + */ +const optionalAuth = async (req, res, next) => { + try { + // Check session first + if (req.session.userId) { + const user = await User.findById(req.session.userId).select('-password'); + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + + // Check JWT token if no session + if (!req.user) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + + if (token) { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findById(decoded.userId).select('-password'); + + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + } + + next(); + } catch (error) { + // Continue without authentication if token is invalid + next(); + } +}; + +module.exports = { + authenticateToken, + authenticateSession, + requireAdmin, + requireAdminSession, + optionalAuth +}; \ No newline at end of file diff --git a/.history/middleware/auth_20251019202048.js b/.history/middleware/auth_20251019202048.js new file mode 100644 index 0000000..a76c5f2 --- /dev/null +++ b/.history/middleware/auth_20251019202048.js @@ -0,0 +1,156 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models'); + +/** + * Authentication middleware + * Verifies JWT token and attaches user to request + */ +const authenticateToken = async (req, res, next) => { + try { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN + + if (!token) { + return res.status(401).json({ + success: false, + message: 'Access token required' + }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + return res.status(401).json({ + success: false, + message: 'Invalid or inactive user' + }); + } + + req.user = user; + next(); + } catch (error) { + console.error('Token verification error:', error); + return res.status(403).json({ + success: false, + message: 'Invalid token' + }); + } +}; + +/** + * Session-based authentication middleware + * For web pages using sessions + */ +const authenticateSession = async (req, res, next) => { + try { + if (!req.session.userId) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + const user = await User.findById(req.session.userId).select('-password'); + + if (!user || !user.isActive) { + req.session.destroy(); + req.flash('error', '유효하지 않은 사용자입니다.'); + return res.redirect('/auth/login'); + } + + req.user = user; + res.locals.user = user; + next(); + } catch (error) { + console.error('Session authentication error:', error); + req.session.destroy(); + req.flash('error', '인증 오류가 발생했습니다.'); + return res.redirect('/auth/login'); + } +}; + +/** + * Admin role middleware + * Requires user to be authenticated and have admin role + */ +const requireAdmin = (req, res, next) => { + if (!req.user) { + return res.status(401).json({ + success: false, + message: 'Authentication required' + }); + } + + if (req.user.role !== 'admin') { + return res.status(403).json({ + success: false, + message: 'Admin access required' + }); + } + + next(); +}; + +/** + * Admin session middleware for web pages + */ +const requireAdminSession = (req, res, next) => { + if (!req.user) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + if (req.user.role !== 'admin') { + req.flash('error', '관리자 권한이 필요합니다.'); + return res.redirect('/'); + } + + next(); +}; + +/** + * Optional authentication middleware + * Attaches user if token exists but doesn't require it + */ +const optionalAuth = async (req, res, next) => { + try { + // Check session first + if (req.session.userId) { + const user = await User.findById(req.session.userId).select('-password'); + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + + // Check JWT token if no session + if (!req.user) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + + if (token) { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findById(decoded.userId).select('-password'); + + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + } + + next(); + } catch (error) { + // Continue without authentication if token is invalid + next(); + } +}; + +module.exports = { + authenticateToken, + authenticateSession, + requireAdmin, + requireAdminSession, + optionalAuth +}; \ No newline at end of file diff --git a/.history/middleware/auth_20251019202102.js b/.history/middleware/auth_20251019202102.js new file mode 100644 index 0000000..50bd0e7 --- /dev/null +++ b/.history/middleware/auth_20251019202102.js @@ -0,0 +1,158 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models'); + +/** + * Authentication middleware + * Verifies JWT token and attaches user to request + */ +const authenticateToken = async (req, res, next) => { + try { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN + + if (!token) { + return res.status(401).json({ + success: false, + message: 'Access token required' + }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + return res.status(401).json({ + success: false, + message: 'Invalid or inactive user' + }); + } + + req.user = user; + next(); + } catch (error) { + console.error('Token verification error:', error); + return res.status(403).json({ + success: false, + message: 'Invalid token' + }); + } +}; + +/** + * Session-based authentication middleware + * For web pages using sessions + */ +const authenticateSession = async (req, res, next) => { + try { + if (!req.session.userId) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + const user = await User.findByPk(req.session.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + req.session.destroy(); + req.flash('error', '유효하지 않은 사용자입니다.'); + return res.redirect('/auth/login'); + } + + req.user = user; + res.locals.user = user; + next(); + } catch (error) { + console.error('Session authentication error:', error); + req.session.destroy(); + req.flash('error', '인증 오류가 발생했습니다.'); + return res.redirect('/auth/login'); + } +}; + +/** + * Admin role middleware + * Requires user to be authenticated and have admin role + */ +const requireAdmin = (req, res, next) => { + if (!req.user) { + return res.status(401).json({ + success: false, + message: 'Authentication required' + }); + } + + if (req.user.role !== 'admin') { + return res.status(403).json({ + success: false, + message: 'Admin access required' + }); + } + + next(); +}; + +/** + * Admin session middleware for web pages + */ +const requireAdminSession = (req, res, next) => { + if (!req.user) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + if (req.user.role !== 'admin') { + req.flash('error', '관리자 권한이 필요합니다.'); + return res.redirect('/'); + } + + next(); +}; + +/** + * Optional authentication middleware + * Attaches user if token exists but doesn't require it + */ +const optionalAuth = async (req, res, next) => { + try { + // Check session first + if (req.session.userId) { + const user = await User.findById(req.session.userId).select('-password'); + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + + // Check JWT token if no session + if (!req.user) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + + if (token) { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findById(decoded.userId).select('-password'); + + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + } + + next(); + } catch (error) { + // Continue without authentication if token is invalid + next(); + } +}; + +module.exports = { + authenticateToken, + authenticateSession, + requireAdmin, + requireAdminSession, + optionalAuth +}; \ No newline at end of file diff --git a/.history/middleware/auth_20251019202112.js b/.history/middleware/auth_20251019202112.js new file mode 100644 index 0000000..cee7633 --- /dev/null +++ b/.history/middleware/auth_20251019202112.js @@ -0,0 +1,162 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models'); + +/** + * Authentication middleware + * Verifies JWT token and attaches user to request + */ +const authenticateToken = async (req, res, next) => { + try { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN + + if (!token) { + return res.status(401).json({ + success: false, + message: 'Access token required' + }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + return res.status(401).json({ + success: false, + message: 'Invalid or inactive user' + }); + } + + req.user = user; + next(); + } catch (error) { + console.error('Token verification error:', error); + return res.status(403).json({ + success: false, + message: 'Invalid token' + }); + } +}; + +/** + * Session-based authentication middleware + * For web pages using sessions + */ +const authenticateSession = async (req, res, next) => { + try { + if (!req.session.userId) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + const user = await User.findByPk(req.session.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + req.session.destroy(); + req.flash('error', '유효하지 않은 사용자입니다.'); + return res.redirect('/auth/login'); + } + + req.user = user; + res.locals.user = user; + next(); + } catch (error) { + console.error('Session authentication error:', error); + req.session.destroy(); + req.flash('error', '인증 오류가 발생했습니다.'); + return res.redirect('/auth/login'); + } +}; + +/** + * Admin role middleware + * Requires user to be authenticated and have admin role + */ +const requireAdmin = (req, res, next) => { + if (!req.user) { + return res.status(401).json({ + success: false, + message: 'Authentication required' + }); + } + + if (req.user.role !== 'admin') { + return res.status(403).json({ + success: false, + message: 'Admin access required' + }); + } + + next(); +}; + +/** + * Admin session middleware for web pages + */ +const requireAdminSession = (req, res, next) => { + if (!req.user) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + if (req.user.role !== 'admin') { + req.flash('error', '관리자 권한이 필요합니다.'); + return res.redirect('/'); + } + + next(); +}; + +/** + * Optional authentication middleware + * Attaches user if token exists but doesn't require it + */ +const optionalAuth = async (req, res, next) => { + try { + // Check session first + if (req.session.userId) { + const user = await User.findByPk(req.session.userId, { + attributes: { exclude: ['password'] } + }); + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + + // Check JWT token if no session + if (!req.user) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + + if (token) { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId, { + attributes: { exclude: ['password'] } + }); + + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + } + + next(); + } catch (error) { + // Continue without authentication if token is invalid + next(); + } +}; + +module.exports = { + authenticateToken, + authenticateSession, + requireAdmin, + requireAdminSession, + optionalAuth +}; \ No newline at end of file diff --git a/.history/middleware/auth_20251019202631.js b/.history/middleware/auth_20251019202631.js new file mode 100644 index 0000000..cee7633 --- /dev/null +++ b/.history/middleware/auth_20251019202631.js @@ -0,0 +1,162 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models'); + +/** + * Authentication middleware + * Verifies JWT token and attaches user to request + */ +const authenticateToken = async (req, res, next) => { + try { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN + + if (!token) { + return res.status(401).json({ + success: false, + message: 'Access token required' + }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + return res.status(401).json({ + success: false, + message: 'Invalid or inactive user' + }); + } + + req.user = user; + next(); + } catch (error) { + console.error('Token verification error:', error); + return res.status(403).json({ + success: false, + message: 'Invalid token' + }); + } +}; + +/** + * Session-based authentication middleware + * For web pages using sessions + */ +const authenticateSession = async (req, res, next) => { + try { + if (!req.session.userId) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + const user = await User.findByPk(req.session.userId, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + req.session.destroy(); + req.flash('error', '유효하지 않은 사용자입니다.'); + return res.redirect('/auth/login'); + } + + req.user = user; + res.locals.user = user; + next(); + } catch (error) { + console.error('Session authentication error:', error); + req.session.destroy(); + req.flash('error', '인증 오류가 발생했습니다.'); + return res.redirect('/auth/login'); + } +}; + +/** + * Admin role middleware + * Requires user to be authenticated and have admin role + */ +const requireAdmin = (req, res, next) => { + if (!req.user) { + return res.status(401).json({ + success: false, + message: 'Authentication required' + }); + } + + if (req.user.role !== 'admin') { + return res.status(403).json({ + success: false, + message: 'Admin access required' + }); + } + + next(); +}; + +/** + * Admin session middleware for web pages + */ +const requireAdminSession = (req, res, next) => { + if (!req.user) { + req.flash('error', '로그인이 필요합니다.'); + return res.redirect('/auth/login'); + } + + if (req.user.role !== 'admin') { + req.flash('error', '관리자 권한이 필요합니다.'); + return res.redirect('/'); + } + + next(); +}; + +/** + * Optional authentication middleware + * Attaches user if token exists but doesn't require it + */ +const optionalAuth = async (req, res, next) => { + try { + // Check session first + if (req.session.userId) { + const user = await User.findByPk(req.session.userId, { + attributes: { exclude: ['password'] } + }); + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + + // Check JWT token if no session + if (!req.user) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + + if (token) { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId, { + attributes: { exclude: ['password'] } + }); + + if (user && user.isActive) { + req.user = user; + res.locals.user = user; + } + } + } + + next(); + } catch (error) { + // Continue without authentication if token is invalid + next(); + } +}; + +module.exports = { + authenticateToken, + authenticateSession, + requireAdmin, + requireAdminSession, + optionalAuth +}; \ No newline at end of file diff --git a/.history/models/Banner_20251022194806.js b/.history/models/Banner_20251022194806.js new file mode 100644 index 0000000..ab3dd28 --- /dev/null +++ b/.history/models/Banner_20251022194806.js @@ -0,0 +1,195 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Banner = sequelize.define('Banner', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + title: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notEmpty: true, + len: [1, 200] + } + }, + subtitle: { + type: DataTypes.STRING, + allowNull: true, + validate: { + len: [0, 300] + } + }, + description: { + type: DataTypes.TEXT, + allowNull: true + }, + buttonText: { + type: DataTypes.STRING, + allowNull: true, + validate: { + len: [0, 50] + } + }, + buttonUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl: true + } + }, + image: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Banner background image URL' + }, + mobileImage: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Mobile-optimized banner image URL' + }, + position: { + type: DataTypes.ENUM('hero', 'secondary', 'footer'), + defaultValue: 'hero', + allowNull: false + }, + order: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false, + comment: 'Display order (lower numbers appear first)' + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false + }, + startDate: { + type: DataTypes.DATE, + allowNull: true, + comment: 'Banner start display date' + }, + endDate: { + type: DataTypes.DATE, + allowNull: true, + comment: 'Banner end display date' + }, + clickCount: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false + }, + impressions: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false + }, + targetAudience: { + type: DataTypes.ENUM('all', 'mobile', 'desktop'), + defaultValue: 'all', + allowNull: false + }, + backgroundColor: { + type: DataTypes.STRING, + allowNull: true, + validate: { + is: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ + }, + comment: 'Hex color code for banner background' + }, + textColor: { + type: DataTypes.STRING, + allowNull: true, + validate: { + is: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ + }, + comment: 'Hex color code for banner text' + }, + animation: { + type: DataTypes.ENUM('none', 'fade', 'slide', 'zoom'), + defaultValue: 'none', + allowNull: false + }, + metadata: { + type: DataTypes.JSONB, + allowNull: true, + defaultValue: {}, + comment: 'Additional banner metadata and settings' + } +}, { + tableName: 'banners', + timestamps: true, + paranoid: true, + indexes: [ + { + fields: ['isActive'] + }, + { + fields: ['position'] + }, + { + fields: ['order'] + }, + { + fields: ['startDate', 'endDate'] + } + ] +}); + +// Virtual field for checking if banner is currently active +Banner.prototype.isCurrentlyActive = function() { + if (!this.isActive) return false; + + const now = new Date(); + + if (this.startDate && now < this.startDate) return false; + if (this.endDate && now > this.endDate) return false; + + return true; +}; + +// Method to increment click count +Banner.prototype.recordClick = async function() { + this.clickCount += 1; + await this.save(); + return this; +}; + +// Method to increment impressions +Banner.prototype.recordImpression = async function() { + this.impressions += 1; + await this.save(); + return this; +}; + +// Static method to get active banners +Banner.getActiveBanners = async function(position = null) { + const whereClause = { + isActive: true + }; + + if (position) { + whereClause.position = position; + } + + const now = new Date(); + + return await this.findAll({ + where: { + ...whereClause, + [require('sequelize').Op.or]: [ + { startDate: null }, + { startDate: { [require('sequelize').Op.lte]: now } } + ], + [require('sequelize').Op.or]: [ + { endDate: null }, + { endDate: { [require('sequelize').Op.gte]: now } } + ] + }, + order: [['order', 'ASC'], ['createdAt', 'DESC']] + }); +}; + +module.exports = Banner; \ No newline at end of file diff --git a/.history/models/Banner_20251022195905.js b/.history/models/Banner_20251022195905.js new file mode 100644 index 0000000..ab3dd28 --- /dev/null +++ b/.history/models/Banner_20251022195905.js @@ -0,0 +1,195 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Banner = sequelize.define('Banner', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + title: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notEmpty: true, + len: [1, 200] + } + }, + subtitle: { + type: DataTypes.STRING, + allowNull: true, + validate: { + len: [0, 300] + } + }, + description: { + type: DataTypes.TEXT, + allowNull: true + }, + buttonText: { + type: DataTypes.STRING, + allowNull: true, + validate: { + len: [0, 50] + } + }, + buttonUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl: true + } + }, + image: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Banner background image URL' + }, + mobileImage: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Mobile-optimized banner image URL' + }, + position: { + type: DataTypes.ENUM('hero', 'secondary', 'footer'), + defaultValue: 'hero', + allowNull: false + }, + order: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false, + comment: 'Display order (lower numbers appear first)' + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false + }, + startDate: { + type: DataTypes.DATE, + allowNull: true, + comment: 'Banner start display date' + }, + endDate: { + type: DataTypes.DATE, + allowNull: true, + comment: 'Banner end display date' + }, + clickCount: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false + }, + impressions: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false + }, + targetAudience: { + type: DataTypes.ENUM('all', 'mobile', 'desktop'), + defaultValue: 'all', + allowNull: false + }, + backgroundColor: { + type: DataTypes.STRING, + allowNull: true, + validate: { + is: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ + }, + comment: 'Hex color code for banner background' + }, + textColor: { + type: DataTypes.STRING, + allowNull: true, + validate: { + is: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ + }, + comment: 'Hex color code for banner text' + }, + animation: { + type: DataTypes.ENUM('none', 'fade', 'slide', 'zoom'), + defaultValue: 'none', + allowNull: false + }, + metadata: { + type: DataTypes.JSONB, + allowNull: true, + defaultValue: {}, + comment: 'Additional banner metadata and settings' + } +}, { + tableName: 'banners', + timestamps: true, + paranoid: true, + indexes: [ + { + fields: ['isActive'] + }, + { + fields: ['position'] + }, + { + fields: ['order'] + }, + { + fields: ['startDate', 'endDate'] + } + ] +}); + +// Virtual field for checking if banner is currently active +Banner.prototype.isCurrentlyActive = function() { + if (!this.isActive) return false; + + const now = new Date(); + + if (this.startDate && now < this.startDate) return false; + if (this.endDate && now > this.endDate) return false; + + return true; +}; + +// Method to increment click count +Banner.prototype.recordClick = async function() { + this.clickCount += 1; + await this.save(); + return this; +}; + +// Method to increment impressions +Banner.prototype.recordImpression = async function() { + this.impressions += 1; + await this.save(); + return this; +}; + +// Static method to get active banners +Banner.getActiveBanners = async function(position = null) { + const whereClause = { + isActive: true + }; + + if (position) { + whereClause.position = position; + } + + const now = new Date(); + + return await this.findAll({ + where: { + ...whereClause, + [require('sequelize').Op.or]: [ + { startDate: null }, + { startDate: { [require('sequelize').Op.lte]: now } } + ], + [require('sequelize').Op.or]: [ + { endDate: null }, + { endDate: { [require('sequelize').Op.gte]: now } } + ] + }, + order: [['order', 'ASC'], ['createdAt', 'DESC']] + }); +}; + +module.exports = Banner; \ No newline at end of file diff --git a/.history/models/Contact_20251019201845.js b/.history/models/Contact_20251019201845.js new file mode 100644 index 0000000..be16e21 --- /dev/null +++ b/.history/models/Contact_20251019201845.js @@ -0,0 +1,108 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Contact = sequelize.define('Contact', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + name: { + type: DataTypes.STRING, + allowNull: false, + set(value) { + this.setDataValue('name', value.trim()); + } + }, + email: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isEmail: true + }, + set(value) { + this.setDataValue('email', value.toLowerCase().trim()); + } + }, + phone: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + this.setDataValue('phone', value ? value.trim() : null); + } + }, + company: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + this.setDataValue('company', value ? value.trim() : null); + } + }, + subject: { + type: DataTypes.STRING, + allowNull: false, + set(value) { + this.setDataValue('subject', value.trim()); + } + }, + message: { + type: DataTypes.TEXT, + allowNull: false + }, + serviceInterest: { + type: DataTypes.ENUM('web-development', 'mobile-app', 'ui-ux-design', 'branding', 'consulting', 'other'), + allowNull: true + }, + budget: { + type: DataTypes.ENUM('under-1m', '1m-5m', '5m-10m', '10m-20m', '20m-50m', 'over-50m'), + allowNull: true + }, + timeline: { + type: DataTypes.ENUM('asap', '1-month', '1-3-months', '3-6-months', 'flexible'), + allowNull: true + }, + status: { + type: DataTypes.ENUM('new', 'in-progress', 'replied', 'closed'), + defaultValue: 'new' + }, + priority: { + type: DataTypes.ENUM('low', 'medium', 'high', 'urgent'), + defaultValue: 'medium' + }, + source: { + type: DataTypes.ENUM('website', 'telegram', 'email', 'phone', 'referral'), + defaultValue: 'website' + }, + isRead: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + adminNotes: { + type: DataTypes.TEXT, + allowNull: true + }, + ipAddress: { + type: DataTypes.STRING, + allowNull: true + }, + userAgent: { + type: DataTypes.TEXT, + allowNull: true + } +}, { + tableName: 'contacts', + timestamps: true, + indexes: [ + { + fields: ['status', 'createdAt'] + }, + { + fields: ['isRead', 'createdAt'] + }, + { + fields: ['email'] + } + ] +}); + +module.exports = Contact; \ No newline at end of file diff --git a/.history/models/Contact_20251019202631.js b/.history/models/Contact_20251019202631.js new file mode 100644 index 0000000..be16e21 --- /dev/null +++ b/.history/models/Contact_20251019202631.js @@ -0,0 +1,108 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Contact = sequelize.define('Contact', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + name: { + type: DataTypes.STRING, + allowNull: false, + set(value) { + this.setDataValue('name', value.trim()); + } + }, + email: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isEmail: true + }, + set(value) { + this.setDataValue('email', value.toLowerCase().trim()); + } + }, + phone: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + this.setDataValue('phone', value ? value.trim() : null); + } + }, + company: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + this.setDataValue('company', value ? value.trim() : null); + } + }, + subject: { + type: DataTypes.STRING, + allowNull: false, + set(value) { + this.setDataValue('subject', value.trim()); + } + }, + message: { + type: DataTypes.TEXT, + allowNull: false + }, + serviceInterest: { + type: DataTypes.ENUM('web-development', 'mobile-app', 'ui-ux-design', 'branding', 'consulting', 'other'), + allowNull: true + }, + budget: { + type: DataTypes.ENUM('under-1m', '1m-5m', '5m-10m', '10m-20m', '20m-50m', 'over-50m'), + allowNull: true + }, + timeline: { + type: DataTypes.ENUM('asap', '1-month', '1-3-months', '3-6-months', 'flexible'), + allowNull: true + }, + status: { + type: DataTypes.ENUM('new', 'in-progress', 'replied', 'closed'), + defaultValue: 'new' + }, + priority: { + type: DataTypes.ENUM('low', 'medium', 'high', 'urgent'), + defaultValue: 'medium' + }, + source: { + type: DataTypes.ENUM('website', 'telegram', 'email', 'phone', 'referral'), + defaultValue: 'website' + }, + isRead: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + adminNotes: { + type: DataTypes.TEXT, + allowNull: true + }, + ipAddress: { + type: DataTypes.STRING, + allowNull: true + }, + userAgent: { + type: DataTypes.TEXT, + allowNull: true + } +}, { + tableName: 'contacts', + timestamps: true, + indexes: [ + { + fields: ['status', 'createdAt'] + }, + { + fields: ['isRead', 'createdAt'] + }, + { + fields: ['email'] + } + ] +}); + +module.exports = Contact; \ No newline at end of file diff --git a/.history/models/Portfolio_20251019201803.js b/.history/models/Portfolio_20251019201803.js new file mode 100644 index 0000000..089f685 --- /dev/null +++ b/.history/models/Portfolio_20251019201803.js @@ -0,0 +1,121 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Portfolio = sequelize.define('Portfolio', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + title: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [1, 255] + }, + set(value) { + this.setDataValue('title', value.trim()); + } + }, + description: { + type: DataTypes.TEXT, + allowNull: false + }, + shortDescription: { + type: DataTypes.STRING(200), + allowNull: false + }, + category: { + type: DataTypes.ENUM('web-development', 'mobile-app', 'ui-ux-design', 'branding', 'e-commerce', 'other'), + allowNull: false + }, + technologies: { + type: DataTypes.ARRAY(DataTypes.STRING), + defaultValue: [] + }, + images: { + type: DataTypes.JSONB, + defaultValue: [] + }, + clientName: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + this.setDataValue('clientName', value ? value.trim() : null); + } + }, + projectUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl: true + } + }, + githubUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl: true + } + }, + status: { + type: DataTypes.ENUM('completed', 'in-progress', 'planning'), + defaultValue: 'completed' + }, + featured: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + publishedAt: { + type: DataTypes.DATE, + defaultValue: DataTypes.NOW + }, + completedAt: { + type: DataTypes.DATE, + allowNull: true + }, + isPublished: { + type: DataTypes.BOOLEAN, + defaultValue: true + }, + viewCount: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + likes: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + order: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + seo: { + type: DataTypes.JSONB, + defaultValue: {} + } +}, { + tableName: 'portfolios', + timestamps: true, + indexes: [ + { + fields: ['category', 'publishedAt'] + }, + { + fields: ['featured', 'publishedAt'] + }, + { + type: 'gin', + fields: ['technologies'] + } + ] +}); + +// Virtual for primary image +Portfolio.prototype.getPrimaryImage = function() { + if (!this.images || this.images.length === 0) return null; + const primary = this.images.find(img => img.isPrimary); + return primary || this.images[0]; +}; + +module.exports = Portfolio; \ No newline at end of file diff --git a/.history/models/Portfolio_20251019202630.js b/.history/models/Portfolio_20251019202630.js new file mode 100644 index 0000000..089f685 --- /dev/null +++ b/.history/models/Portfolio_20251019202630.js @@ -0,0 +1,121 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Portfolio = sequelize.define('Portfolio', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + title: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [1, 255] + }, + set(value) { + this.setDataValue('title', value.trim()); + } + }, + description: { + type: DataTypes.TEXT, + allowNull: false + }, + shortDescription: { + type: DataTypes.STRING(200), + allowNull: false + }, + category: { + type: DataTypes.ENUM('web-development', 'mobile-app', 'ui-ux-design', 'branding', 'e-commerce', 'other'), + allowNull: false + }, + technologies: { + type: DataTypes.ARRAY(DataTypes.STRING), + defaultValue: [] + }, + images: { + type: DataTypes.JSONB, + defaultValue: [] + }, + clientName: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + this.setDataValue('clientName', value ? value.trim() : null); + } + }, + projectUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl: true + } + }, + githubUrl: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isUrl: true + } + }, + status: { + type: DataTypes.ENUM('completed', 'in-progress', 'planning'), + defaultValue: 'completed' + }, + featured: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + publishedAt: { + type: DataTypes.DATE, + defaultValue: DataTypes.NOW + }, + completedAt: { + type: DataTypes.DATE, + allowNull: true + }, + isPublished: { + type: DataTypes.BOOLEAN, + defaultValue: true + }, + viewCount: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + likes: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + order: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + seo: { + type: DataTypes.JSONB, + defaultValue: {} + } +}, { + tableName: 'portfolios', + timestamps: true, + indexes: [ + { + fields: ['category', 'publishedAt'] + }, + { + fields: ['featured', 'publishedAt'] + }, + { + type: 'gin', + fields: ['technologies'] + } + ] +}); + +// Virtual for primary image +Portfolio.prototype.getPrimaryImage = function() { + if (!this.images || this.images.length === 0) return null; + const primary = this.images.find(img => img.isPrimary); + return primary || this.images[0]; +}; + +module.exports = Portfolio; \ No newline at end of file diff --git a/.history/models/Service_20251019201824.js b/.history/models/Service_20251019201824.js new file mode 100644 index 0000000..61a9098 --- /dev/null +++ b/.history/models/Service_20251019201824.js @@ -0,0 +1,96 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Service = sequelize.define('Service', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [1, 255] + }, + set(value) { + this.setDataValue('name', value.trim()); + } + }, + description: { + type: DataTypes.TEXT, + allowNull: false + }, + shortDescription: { + type: DataTypes.STRING(150), + allowNull: false + }, + icon: { + type: DataTypes.STRING, + allowNull: false + }, + category: { + type: DataTypes.ENUM('development', 'design', 'consulting', 'marketing', 'maintenance'), + allowNull: false + }, + features: { + type: DataTypes.JSONB, + defaultValue: [] + }, + pricing: { + type: DataTypes.JSONB, + allowNull: false, + validate: { + isValidPricing(value) { + if (!value.basePrice || value.basePrice < 0) { + throw new Error('Base price must be a positive number'); + } + } + } + }, + estimatedTime: { + type: DataTypes.JSONB, + allowNull: false, + validate: { + isValidTime(value) { + if (!value.min || !value.max || value.min > value.max) { + throw new Error('Invalid estimated time range'); + } + } + } + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: true + }, + featured: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + order: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + tags: { + type: DataTypes.ARRAY(DataTypes.STRING), + defaultValue: [] + }, + seo: { + type: DataTypes.JSONB, + defaultValue: {} + } +}, { + tableName: 'services', + timestamps: true, + indexes: [ + { + fields: ['category', 'featured', 'order'] + }, + { + type: 'gin', + fields: ['tags'] + } + ] +}); + +module.exports = Service; \ No newline at end of file diff --git a/.history/models/Service_20251019202630.js b/.history/models/Service_20251019202630.js new file mode 100644 index 0000000..61a9098 --- /dev/null +++ b/.history/models/Service_20251019202630.js @@ -0,0 +1,96 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Service = sequelize.define('Service', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [1, 255] + }, + set(value) { + this.setDataValue('name', value.trim()); + } + }, + description: { + type: DataTypes.TEXT, + allowNull: false + }, + shortDescription: { + type: DataTypes.STRING(150), + allowNull: false + }, + icon: { + type: DataTypes.STRING, + allowNull: false + }, + category: { + type: DataTypes.ENUM('development', 'design', 'consulting', 'marketing', 'maintenance'), + allowNull: false + }, + features: { + type: DataTypes.JSONB, + defaultValue: [] + }, + pricing: { + type: DataTypes.JSONB, + allowNull: false, + validate: { + isValidPricing(value) { + if (!value.basePrice || value.basePrice < 0) { + throw new Error('Base price must be a positive number'); + } + } + } + }, + estimatedTime: { + type: DataTypes.JSONB, + allowNull: false, + validate: { + isValidTime(value) { + if (!value.min || !value.max || value.min > value.max) { + throw new Error('Invalid estimated time range'); + } + } + } + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: true + }, + featured: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + order: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + tags: { + type: DataTypes.ARRAY(DataTypes.STRING), + defaultValue: [] + }, + seo: { + type: DataTypes.JSONB, + defaultValue: {} + } +}, { + tableName: 'services', + timestamps: true, + indexes: [ + { + fields: ['category', 'featured', 'order'] + }, + { + type: 'gin', + fields: ['tags'] + } + ] +}); + +module.exports = Service; \ No newline at end of file diff --git a/.history/models/SiteSettings_20251019201906.js b/.history/models/SiteSettings_20251019201906.js new file mode 100644 index 0000000..a8574c2 --- /dev/null +++ b/.history/models/SiteSettings_20251019201906.js @@ -0,0 +1,82 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const SiteSettings = sequelize.define('SiteSettings', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + siteName: { + type: DataTypes.STRING, + defaultValue: 'SmartSolTech' + }, + siteDescription: { + type: DataTypes.TEXT, + defaultValue: 'Innovative technology solutions for modern businesses' + }, + logo: { + type: DataTypes.STRING, + defaultValue: '/images/logo.png' + }, + favicon: { + type: DataTypes.STRING, + defaultValue: '/images/favicon.ico' + }, + contact: { + type: DataTypes.JSONB, + defaultValue: { + email: 'info@smartsoltech.kr', + phone: '+82-10-0000-0000', + address: 'Seoul, South Korea' + } + }, + social: { + type: DataTypes.JSONB, + defaultValue: {} + }, + telegram: { + type: DataTypes.JSONB, + defaultValue: { + isEnabled: false + } + }, + seo: { + type: DataTypes.JSONB, + defaultValue: { + metaTitle: 'SmartSolTech - Technology Solutions', + metaDescription: 'Professional web development, mobile apps, and digital solutions in Korea', + keywords: 'web development, mobile apps, UI/UX design, Korea, technology' + } + }, + hero: { + type: DataTypes.JSONB, + defaultValue: { + title: 'Smart Technology Solutions', + subtitle: 'We create innovative digital experiences that drive business growth', + backgroundImage: '/images/hero-bg.jpg', + ctaText: 'Get Started', + ctaLink: '#contact' + } + }, + about: { + type: DataTypes.JSONB, + defaultValue: { + title: 'About SmartSolTech', + description: 'We are a team of passionate developers and designers creating cutting-edge technology solutions.', + image: '/images/about.jpg' + } + }, + maintenance: { + type: DataTypes.JSONB, + defaultValue: { + isEnabled: false, + message: 'We are currently performing maintenance. Please check back soon.' + } + } +}, { + tableName: 'site_settings', + timestamps: true +}); + +module.exports = SiteSettings; \ No newline at end of file diff --git a/.history/models/SiteSettings_20251019202631.js b/.history/models/SiteSettings_20251019202631.js new file mode 100644 index 0000000..a8574c2 --- /dev/null +++ b/.history/models/SiteSettings_20251019202631.js @@ -0,0 +1,82 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const SiteSettings = sequelize.define('SiteSettings', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + siteName: { + type: DataTypes.STRING, + defaultValue: 'SmartSolTech' + }, + siteDescription: { + type: DataTypes.TEXT, + defaultValue: 'Innovative technology solutions for modern businesses' + }, + logo: { + type: DataTypes.STRING, + defaultValue: '/images/logo.png' + }, + favicon: { + type: DataTypes.STRING, + defaultValue: '/images/favicon.ico' + }, + contact: { + type: DataTypes.JSONB, + defaultValue: { + email: 'info@smartsoltech.kr', + phone: '+82-10-0000-0000', + address: 'Seoul, South Korea' + } + }, + social: { + type: DataTypes.JSONB, + defaultValue: {} + }, + telegram: { + type: DataTypes.JSONB, + defaultValue: { + isEnabled: false + } + }, + seo: { + type: DataTypes.JSONB, + defaultValue: { + metaTitle: 'SmartSolTech - Technology Solutions', + metaDescription: 'Professional web development, mobile apps, and digital solutions in Korea', + keywords: 'web development, mobile apps, UI/UX design, Korea, technology' + } + }, + hero: { + type: DataTypes.JSONB, + defaultValue: { + title: 'Smart Technology Solutions', + subtitle: 'We create innovative digital experiences that drive business growth', + backgroundImage: '/images/hero-bg.jpg', + ctaText: 'Get Started', + ctaLink: '#contact' + } + }, + about: { + type: DataTypes.JSONB, + defaultValue: { + title: 'About SmartSolTech', + description: 'We are a team of passionate developers and designers creating cutting-edge technology solutions.', + image: '/images/about.jpg' + } + }, + maintenance: { + type: DataTypes.JSONB, + defaultValue: { + isEnabled: false, + message: 'We are currently performing maintenance. Please check back soon.' + } + } +}, { + tableName: 'site_settings', + timestamps: true +}); + +module.exports = SiteSettings; \ No newline at end of file diff --git a/.history/models/User_20251019201741.js b/.history/models/User_20251019201741.js new file mode 100644 index 0000000..8643388 --- /dev/null +++ b/.history/models/User_20251019201741.js @@ -0,0 +1,78 @@ +const { DataTypes } = require('sequelize'); +const bcrypt = require('bcryptjs'); +const { sequelize } = require('../config/database'); + +const User = sequelize.define('User', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + validate: { + isEmail: true + }, + set(value) { + this.setDataValue('email', value.toLowerCase().trim()); + } + }, + password: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [6, 255] + } + }, + name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [1, 100] + }, + set(value) { + this.setDataValue('name', value.trim()); + } + }, + role: { + type: DataTypes.ENUM('admin', 'moderator'), + defaultValue: 'admin' + }, + avatar: { + type: DataTypes.STRING, + allowNull: true + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: true + }, + lastLogin: { + type: DataTypes.DATE, + allowNull: true + } +}, { + tableName: 'users', + timestamps: true, + hooks: { + beforeSave: async (user) => { + if (user.changed('password')) { + const salt = await bcrypt.genSalt(12); + user.password = await bcrypt.hash(user.password, salt); + } + } + } +}); + +// Instance methods +User.prototype.comparePassword = async function(candidatePassword) { + return bcrypt.compare(candidatePassword, this.password); +}; + +User.prototype.updateLastLogin = function() { + this.lastLogin = new Date(); + return this.save(); +}; + +module.exports = User; \ No newline at end of file diff --git a/.history/models/User_20251019202630.js b/.history/models/User_20251019202630.js new file mode 100644 index 0000000..8643388 --- /dev/null +++ b/.history/models/User_20251019202630.js @@ -0,0 +1,78 @@ +const { DataTypes } = require('sequelize'); +const bcrypt = require('bcryptjs'); +const { sequelize } = require('../config/database'); + +const User = sequelize.define('User', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + validate: { + isEmail: true + }, + set(value) { + this.setDataValue('email', value.toLowerCase().trim()); + } + }, + password: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [6, 255] + } + }, + name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [1, 100] + }, + set(value) { + this.setDataValue('name', value.trim()); + } + }, + role: { + type: DataTypes.ENUM('admin', 'moderator'), + defaultValue: 'admin' + }, + avatar: { + type: DataTypes.STRING, + allowNull: true + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: true + }, + lastLogin: { + type: DataTypes.DATE, + allowNull: true + } +}, { + tableName: 'users', + timestamps: true, + hooks: { + beforeSave: async (user) => { + if (user.changed('password')) { + const salt = await bcrypt.genSalt(12); + user.password = await bcrypt.hash(user.password, salt); + } + } + } +}); + +// Instance methods +User.prototype.comparePassword = async function(candidatePassword) { + return bcrypt.compare(candidatePassword, this.password); +}; + +User.prototype.updateLastLogin = function() { + this.lastLogin = new Date(); + return this.save(); +}; + +module.exports = User; \ No newline at end of file diff --git a/.history/models/index_20251019201914.js b/.history/models/index_20251019201914.js new file mode 100644 index 0000000..659182c --- /dev/null +++ b/.history/models/index_20251019201914.js @@ -0,0 +1,23 @@ +const { sequelize } = require('../config/database'); + +// Import models +const User = require('./User'); +const Portfolio = require('./Portfolio'); +const Service = require('./Service'); +const Contact = require('./Contact'); +const SiteSettings = require('./SiteSettings'); + +// Define associations here if needed +// For example: +// Service.belongsToMany(Portfolio, { through: 'ServicePortfolio' }); +// Portfolio.belongsToMany(Service, { through: 'ServicePortfolio' }); + +// Export models and sequelize instance +module.exports = { + sequelize, + User, + Portfolio, + Service, + Contact, + SiteSettings +}; \ No newline at end of file diff --git a/.history/models/index_20251019202631.js b/.history/models/index_20251019202631.js new file mode 100644 index 0000000..659182c --- /dev/null +++ b/.history/models/index_20251019202631.js @@ -0,0 +1,23 @@ +const { sequelize } = require('../config/database'); + +// Import models +const User = require('./User'); +const Portfolio = require('./Portfolio'); +const Service = require('./Service'); +const Contact = require('./Contact'); +const SiteSettings = require('./SiteSettings'); + +// Define associations here if needed +// For example: +// Service.belongsToMany(Portfolio, { through: 'ServicePortfolio' }); +// Portfolio.belongsToMany(Service, { through: 'ServicePortfolio' }); + +// Export models and sequelize instance +module.exports = { + sequelize, + User, + Portfolio, + Service, + Contact, + SiteSettings +}; \ No newline at end of file diff --git a/.history/models/index_20251022194816.js b/.history/models/index_20251022194816.js new file mode 100644 index 0000000..2a040ac --- /dev/null +++ b/.history/models/index_20251022194816.js @@ -0,0 +1,25 @@ +const { sequelize } = require('../config/database'); + +// Import models +const User = require('./User'); +const Portfolio = require('./Portfolio'); +const Service = require('./Service'); +const Contact = require('./Contact'); +const SiteSettings = require('./SiteSettings'); +const Banner = require('./Banner'); + +// Define associations here if needed +// For example: +// Service.belongsToMany(Portfolio, { through: 'ServicePortfolio' }); +// Portfolio.belongsToMany(Service, { through: 'ServicePortfolio' }); + +// Export models and sequelize instance +module.exports = { + sequelize, + User, + Portfolio, + Service, + Contact, + SiteSettings, + Banner +}; \ No newline at end of file diff --git a/.history/models/index_20251022195905.js b/.history/models/index_20251022195905.js new file mode 100644 index 0000000..2a040ac --- /dev/null +++ b/.history/models/index_20251022195905.js @@ -0,0 +1,25 @@ +const { sequelize } = require('../config/database'); + +// Import models +const User = require('./User'); +const Portfolio = require('./Portfolio'); +const Service = require('./Service'); +const Contact = require('./Contact'); +const SiteSettings = require('./SiteSettings'); +const Banner = require('./Banner'); + +// Define associations here if needed +// For example: +// Service.belongsToMany(Portfolio, { through: 'ServicePortfolio' }); +// Portfolio.belongsToMany(Service, { through: 'ServicePortfolio' }); + +// Export models and sequelize instance +module.exports = { + sequelize, + User, + Portfolio, + Service, + Contact, + SiteSettings, + Banner +}; \ No newline at end of file diff --git a/.history/package_20251021172116.json b/.history/package_20251021172116.json new file mode 100644 index 0000000..7b42816 --- /dev/null +++ b/.history/package_20251021172116.json @@ -0,0 +1,62 @@ +{ + "name": "smartsoltech-website", + "version": "1.0.0", + "description": "Modern PWA website for SmartSolTech with admin panel and Telegram integration", + "main": "server.js", + "scripts": { + "start": "node server.js", + "demo": "node server-demo.js", + "dev": "node scripts/dev.js", + "build": "node scripts/build.js", + "init-db": "node scripts/init-db.js", + "test": "echo \"Error: no test specified\" && exit 1", + "sync-locales": "node scripts/sync-locales.js" + }, + "keywords": [ + "pwa", + "nodejs", + "express", + "telegram", + "portfolio", + "calculator" + ], + "author": "SmartSolTech", + "license": "MIT", + "dependencies": { + "bcryptjs": "^2.4.3", + "compression": "^1.7.4", + "connect-flash": "^0.1.1", + "connect-session-sequelize": "^8.0.2", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-rate-limit": "^7.1.5", + "express-session": "^1.17.3", + "express-validator": "^7.0.1", + "helmet": "^7.1.0", + "i18n": "^0.15.2", + "jsonwebtoken": "^9.0.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "node-telegram-bot-api": "^0.64.0", + "nodemailer": "^6.9.7", + "pg": "^8.16.3", + "pg-hstore": "^2.3.4", + "sequelize": "^6.37.7", + "sharp": "^0.33.0", + "socket.io": "^4.7.4" + }, + "devDependencies": { + "css-loader": "^6.8.1", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^5.5.3", + "mini-css-extract-plugin": "^2.7.6", + "nodemon": "^3.0.2", + "style-loader": "^3.3.3", + "terser-webpack-plugin": "^5.3.9", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "workbox-webpack-plugin": "^7.0.0" + } +} diff --git a/.history/package_20251021172239.json b/.history/package_20251021172239.json new file mode 100644 index 0000000..7b42816 --- /dev/null +++ b/.history/package_20251021172239.json @@ -0,0 +1,62 @@ +{ + "name": "smartsoltech-website", + "version": "1.0.0", + "description": "Modern PWA website for SmartSolTech with admin panel and Telegram integration", + "main": "server.js", + "scripts": { + "start": "node server.js", + "demo": "node server-demo.js", + "dev": "node scripts/dev.js", + "build": "node scripts/build.js", + "init-db": "node scripts/init-db.js", + "test": "echo \"Error: no test specified\" && exit 1", + "sync-locales": "node scripts/sync-locales.js" + }, + "keywords": [ + "pwa", + "nodejs", + "express", + "telegram", + "portfolio", + "calculator" + ], + "author": "SmartSolTech", + "license": "MIT", + "dependencies": { + "bcryptjs": "^2.4.3", + "compression": "^1.7.4", + "connect-flash": "^0.1.1", + "connect-session-sequelize": "^8.0.2", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-rate-limit": "^7.1.5", + "express-session": "^1.17.3", + "express-validator": "^7.0.1", + "helmet": "^7.1.0", + "i18n": "^0.15.2", + "jsonwebtoken": "^9.0.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "node-telegram-bot-api": "^0.64.0", + "nodemailer": "^6.9.7", + "pg": "^8.16.3", + "pg-hstore": "^2.3.4", + "sequelize": "^6.37.7", + "sharp": "^0.33.0", + "socket.io": "^4.7.4" + }, + "devDependencies": { + "css-loader": "^6.8.1", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^5.5.3", + "mini-css-extract-plugin": "^2.7.6", + "nodemon": "^3.0.2", + "style-loader": "^3.3.3", + "terser-webpack-plugin": "^5.3.9", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "workbox-webpack-plugin": "^7.0.0" + } +} diff --git a/.history/package_20251022203957.json b/.history/package_20251022203957.json new file mode 100644 index 0000000..8db9954 --- /dev/null +++ b/.history/package_20251022203957.json @@ -0,0 +1,64 @@ +{ + "name": "smartsoltech-website", + "version": "1.0.0", + "description": "Modern PWA website for SmartSolTech with admin panel and Telegram integration", + "main": "server.js", + "scripts": { + "start": "node server.js", + "demo": "node server-demo.js", + "dev": "node scripts/dev.js", + "build": "node scripts/build.js", + "init-db": "node scripts/init-db.js", + "test": "echo \"Error: no test specified\" && exit 1", + "sync-locales": "node scripts/sync-locales.js" + }, + "keywords": [ + "pwa", + "nodejs", + "express", + "telegram", + "portfolio", + "calculator" + ], + "author": "SmartSolTech", + "license": "MIT", + "dependencies": { + "axios": "^1.12.2", + "bcryptjs": "^2.4.3", + "compression": "^1.7.4", + "connect-flash": "^0.1.1", + "connect-session-sequelize": "^7.1.7", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-ejs-layouts": "^2.5.1", + "express-rate-limit": "^7.1.5", + "express-session": "^1.17.3", + "express-validator": "^7.0.1", + "helmet": "^7.1.0", + "i18n": "^0.15.2", + "jsonwebtoken": "^9.0.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "node-telegram-bot-api": "^0.64.0", + "nodemailer": "^6.9.7", + "pg": "^8.16.3", + "pg-hstore": "^2.3.4", + "sequelize": "^6.37.7", + "sharp": "^0.33.5", + "socket.io": "^4.7.4" + }, + "devDependencies": { + "css-loader": "^6.8.1", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^5.5.3", + "mini-css-extract-plugin": "^2.7.6", + "nodemon": "^3.0.2", + "style-loader": "^3.3.3", + "terser-webpack-plugin": "^5.3.9", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "workbox-webpack-plugin": "^7.0.0" + } +} diff --git a/.history/package_20251022204114.json b/.history/package_20251022204114.json new file mode 100644 index 0000000..8db9954 --- /dev/null +++ b/.history/package_20251022204114.json @@ -0,0 +1,64 @@ +{ + "name": "smartsoltech-website", + "version": "1.0.0", + "description": "Modern PWA website for SmartSolTech with admin panel and Telegram integration", + "main": "server.js", + "scripts": { + "start": "node server.js", + "demo": "node server-demo.js", + "dev": "node scripts/dev.js", + "build": "node scripts/build.js", + "init-db": "node scripts/init-db.js", + "test": "echo \"Error: no test specified\" && exit 1", + "sync-locales": "node scripts/sync-locales.js" + }, + "keywords": [ + "pwa", + "nodejs", + "express", + "telegram", + "portfolio", + "calculator" + ], + "author": "SmartSolTech", + "license": "MIT", + "dependencies": { + "axios": "^1.12.2", + "bcryptjs": "^2.4.3", + "compression": "^1.7.4", + "connect-flash": "^0.1.1", + "connect-session-sequelize": "^7.1.7", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-ejs-layouts": "^2.5.1", + "express-rate-limit": "^7.1.5", + "express-session": "^1.17.3", + "express-validator": "^7.0.1", + "helmet": "^7.1.0", + "i18n": "^0.15.2", + "jsonwebtoken": "^9.0.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "node-telegram-bot-api": "^0.64.0", + "nodemailer": "^6.9.7", + "pg": "^8.16.3", + "pg-hstore": "^2.3.4", + "sequelize": "^6.37.7", + "sharp": "^0.33.5", + "socket.io": "^4.7.4" + }, + "devDependencies": { + "css-loader": "^6.8.1", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^5.5.3", + "mini-css-extract-plugin": "^2.7.6", + "nodemon": "^3.0.2", + "style-loader": "^3.3.3", + "terser-webpack-plugin": "^5.3.9", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "workbox-webpack-plugin": "^7.0.0" + } +} diff --git a/.history/public/css/base_20251020045405.css b/.history/public/css/base_20251020045405.css new file mode 100644 index 0000000..cced8b5 --- /dev/null +++ b/.history/public/css/base_20251020045405.css @@ -0,0 +1,325 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Hero Section */ +.hero-section { + min-height: 100vh !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + text-align: center !important; + padding: 2rem !important; +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/base_20251020045409.css b/.history/public/css/base_20251020045409.css new file mode 100644 index 0000000..cced8b5 --- /dev/null +++ b/.history/public/css/base_20251020045409.css @@ -0,0 +1,325 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Hero Section */ +.hero-section { + min-height: 100vh !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + text-align: center !important; + padding: 2rem !important; +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/base_20251020050032.css b/.history/public/css/base_20251020050032.css new file mode 100644 index 0000000..8bfbc24 --- /dev/null +++ b/.history/public/css/base_20251020050032.css @@ -0,0 +1,590 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Base CSS - Принудительные стили для правильного отображения */ + +/* Reset и базовые стили */ +* { + box-sizing: border-box !important; +} + +html, body { + margin: 0 !important; + padding: 0 !important; + font-family: 'Inter', system-ui, -apple-system, sans-serif !important; + line-height: 1.6 !important; + color: #333 !important; + scroll-behavior: smooth !important; +} + +body { + padding-top: 80px !important; /* Отступ для фиксированной навигации */ +} + +/* Навигация */ +nav, .navigation { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + height: 80px !important; +} + +.navbar, .nav-container { + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + padding: 1rem 2rem !important; + max-width: 1200px !important; + margin: 0 auto !important; + height: 100% !important; +} + +.logo, .brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #1d4ed8 !important; + text-decoration: none !important; +} + +.nav-links, .menu { + display: flex !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; + gap: 2rem !important; +} + +.nav-links a, .menu a { + color: #374151 !important; + text-decoration: none !important; + font-weight: 500 !important; + transition: color 0.3s ease !important; + padding: 0.5rem 0 !important; +} + +.nav-links a:hover, .menu a:hover { + color: #1d4ed8 !important; +} + +/* Hero секция */ +.hero-section { + min-height: 100vh !important; + background: linear-gradient(135deg, #1e3a8a 0%, #7c3aed 50%, #3730a3 100%) !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + text-align: center !important; + color: white !important; + position: relative !important; + overflow: hidden !important; + margin-top: -80px !important; /* Компенсация отступа */ + padding-top: 80px !important; +} + +.hero-section h1 { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1.5rem !important; + line-height: 1.2 !important; +} + +.hero-section p { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + opacity: 0.9 !important; +} + +/* Кнопки */ +.btn-primary, .btn { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + padding: 1rem 2rem !important; + background: linear-gradient(45deg, #3b82f6, #8b5cf6) !important; + color: white !important; + text-decoration: none !important; + border-radius: 50px !important; + font-weight: 600 !important; + transition: all 0.3s ease !important; + border: none !important; + cursor: pointer !important; + font-size: 1rem !important; +} + +.btn-primary:hover, .btn:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 30px rgba(59, 130, 246, 0.3) !important; +} + +/* Карточки */ +.card-hover, .card { + transition: all 0.3s ease !important; + border-radius: 1rem !important; + overflow: hidden !important; + background: white !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; +} + +.card-hover:hover, .card:hover { + transform: translateY(-8px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Секции */ +section { + padding: 5rem 1rem !important; +} + +.container, .max-w-7xl { + max-width: 1200px !important; + margin: 0 auto !important; + padding-left: 1rem !important; + padding-right: 1rem !important; +} + +/* Грид системы */ +.grid { + display: grid !important; +} + +.grid-cols-1 { + grid-template-columns: 1fr !important; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, 1fr) !important; +} + +.grid-cols-3 { + grid-template-columns: repeat(3, 1fr) !important; +} + +.grid-cols-4 { + grid-template-columns: repeat(4, 1fr) !important; +} + +.gap-8 { + gap: 2rem !important; +} + +/* Заголовки */ +h1, h2, h3, h4, h5, h6 { + color: #1f2937 !important; + font-weight: 600 !important; +} + +h1 { + font-size: 3rem !important; +} + +h2 { + font-size: 2.5rem !important; +} + +h3 { + font-size: 1.75rem !important; +} + +/* Footer */ +footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 1rem 1rem !important; +} + +/* Отзывчивость */ +@media (max-width: 768px) { + .nav-links, .menu { + display: none !important; + } + + body { + padding-top: 60px !important; + } + + nav, .navigation { + height: 60px !important; + } + + .hero-section { + margin-top: -60px !important; + padding-top: 60px !important; + } + + section { + padding: 3rem 1rem !important; + } + + .hero-section h1 { + font-size: 2.5rem !important; + } + + .grid-cols-2, .grid-cols-3, .grid-cols-4 { + grid-template-columns: 1fr !important; + } +} + +/* Дополнительные утилитарные классы */ +.text-center { + text-align: center !important; +} + +.text-white { + color: white !important; +} + +.bg-white { + background-color: white !important; +} + +.rounded-lg { + border-radius: 0.5rem !important; +} + +.rounded-2xl { + border-radius: 1rem !important; +} + +.shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important; +} + +.mb-4 { + margin-bottom: 1rem !important; +} + +.mb-8 { + margin-bottom: 2rem !important; +} + +.p-8 { + padding: 2rem !important; +} + +.flex { + display: flex !important; +} + +.items-center { + align-items: center !important; +} + +.justify-center { + justify-content: center !important; +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/base_20251020050046.css b/.history/public/css/base_20251020050046.css new file mode 100644 index 0000000..c9eacf9 --- /dev/null +++ b/.history/public/css/base_20251020050046.css @@ -0,0 +1,591 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Base CSS - Принудительные стили для правильного отображения */ + +/* Reset и базовые стили */ +* { + box-sizing: border-box !important; +} + +html, body { + margin: 0 !important; + padding: 0 !important; + font-family: 'Inter', system-ui, -apple-system, sans-serif !important; + line-height: 1.6 !important; + color: #333 !important; + scroll-behavior: smooth !important; +} + +body { + padding-top: 80px !important; /* Отступ для фиксированной навигации */ +} + +/* Навигация */ +nav, .navigation { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + -webkit-backdrop-filter: blur(10px) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + height: 80px !important; +} + +.navbar, .nav-container { + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + padding: 1rem 2rem !important; + max-width: 1200px !important; + margin: 0 auto !important; + height: 100% !important; +} + +.logo, .brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #1d4ed8 !important; + text-decoration: none !important; +} + +.nav-links, .menu { + display: flex !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; + gap: 2rem !important; +} + +.nav-links a, .menu a { + color: #374151 !important; + text-decoration: none !important; + font-weight: 500 !important; + transition: color 0.3s ease !important; + padding: 0.5rem 0 !important; +} + +.nav-links a:hover, .menu a:hover { + color: #1d4ed8 !important; +} + +/* Hero секция */ +.hero-section { + min-height: 100vh !important; + background: linear-gradient(135deg, #1e3a8a 0%, #7c3aed 50%, #3730a3 100%) !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + text-align: center !important; + color: white !important; + position: relative !important; + overflow: hidden !important; + margin-top: -80px !important; /* Компенсация отступа */ + padding-top: 80px !important; +} + +.hero-section h1 { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1.5rem !important; + line-height: 1.2 !important; +} + +.hero-section p { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + opacity: 0.9 !important; +} + +/* Кнопки */ +.btn-primary, .btn { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + padding: 1rem 2rem !important; + background: linear-gradient(45deg, #3b82f6, #8b5cf6) !important; + color: white !important; + text-decoration: none !important; + border-radius: 50px !important; + font-weight: 600 !important; + transition: all 0.3s ease !important; + border: none !important; + cursor: pointer !important; + font-size: 1rem !important; +} + +.btn-primary:hover, .btn:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 30px rgba(59, 130, 246, 0.3) !important; +} + +/* Карточки */ +.card-hover, .card { + transition: all 0.3s ease !important; + border-radius: 1rem !important; + overflow: hidden !important; + background: white !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; +} + +.card-hover:hover, .card:hover { + transform: translateY(-8px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Секции */ +section { + padding: 5rem 1rem !important; +} + +.container, .max-w-7xl { + max-width: 1200px !important; + margin: 0 auto !important; + padding-left: 1rem !important; + padding-right: 1rem !important; +} + +/* Грид системы */ +.grid { + display: grid !important; +} + +.grid-cols-1 { + grid-template-columns: 1fr !important; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, 1fr) !important; +} + +.grid-cols-3 { + grid-template-columns: repeat(3, 1fr) !important; +} + +.grid-cols-4 { + grid-template-columns: repeat(4, 1fr) !important; +} + +.gap-8 { + gap: 2rem !important; +} + +/* Заголовки */ +h1, h2, h3, h4, h5, h6 { + color: #1f2937 !important; + font-weight: 600 !important; +} + +h1 { + font-size: 3rem !important; +} + +h2 { + font-size: 2.5rem !important; +} + +h3 { + font-size: 1.75rem !important; +} + +/* Footer */ +footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 1rem 1rem !important; +} + +/* Отзывчивость */ +@media (max-width: 768px) { + .nav-links, .menu { + display: none !important; + } + + body { + padding-top: 60px !important; + } + + nav, .navigation { + height: 60px !important; + } + + .hero-section { + margin-top: -60px !important; + padding-top: 60px !important; + } + + section { + padding: 3rem 1rem !important; + } + + .hero-section h1 { + font-size: 2.5rem !important; + } + + .grid-cols-2, .grid-cols-3, .grid-cols-4 { + grid-template-columns: 1fr !important; + } +} + +/* Дополнительные утилитарные классы */ +.text-center { + text-align: center !important; +} + +.text-white { + color: white !important; +} + +.bg-white { + background-color: white !important; +} + +.rounded-lg { + border-radius: 0.5rem !important; +} + +.rounded-2xl { + border-radius: 1rem !important; +} + +.shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important; +} + +.mb-4 { + margin-bottom: 1rem !important; +} + +.mb-8 { + margin-bottom: 2rem !important; +} + +.p-8 { + padding: 2rem !important; +} + +.flex { + display: flex !important; +} + +.items-center { + align-items: center !important; +} + +.justify-center { + justify-content: center !important; +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/base_20251020050055.css b/.history/public/css/base_20251020050055.css new file mode 100644 index 0000000..c9eacf9 --- /dev/null +++ b/.history/public/css/base_20251020050055.css @@ -0,0 +1,591 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Base CSS - Принудительные стили для правильного отображения */ + +/* Reset и базовые стили */ +* { + box-sizing: border-box !important; +} + +html, body { + margin: 0 !important; + padding: 0 !important; + font-family: 'Inter', system-ui, -apple-system, sans-serif !important; + line-height: 1.6 !important; + color: #333 !important; + scroll-behavior: smooth !important; +} + +body { + padding-top: 80px !important; /* Отступ для фиксированной навигации */ +} + +/* Навигация */ +nav, .navigation { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + -webkit-backdrop-filter: blur(10px) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + height: 80px !important; +} + +.navbar, .nav-container { + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + padding: 1rem 2rem !important; + max-width: 1200px !important; + margin: 0 auto !important; + height: 100% !important; +} + +.logo, .brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #1d4ed8 !important; + text-decoration: none !important; +} + +.nav-links, .menu { + display: flex !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; + gap: 2rem !important; +} + +.nav-links a, .menu a { + color: #374151 !important; + text-decoration: none !important; + font-weight: 500 !important; + transition: color 0.3s ease !important; + padding: 0.5rem 0 !important; +} + +.nav-links a:hover, .menu a:hover { + color: #1d4ed8 !important; +} + +/* Hero секция */ +.hero-section { + min-height: 100vh !important; + background: linear-gradient(135deg, #1e3a8a 0%, #7c3aed 50%, #3730a3 100%) !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + text-align: center !important; + color: white !important; + position: relative !important; + overflow: hidden !important; + margin-top: -80px !important; /* Компенсация отступа */ + padding-top: 80px !important; +} + +.hero-section h1 { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1.5rem !important; + line-height: 1.2 !important; +} + +.hero-section p { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + opacity: 0.9 !important; +} + +/* Кнопки */ +.btn-primary, .btn { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + padding: 1rem 2rem !important; + background: linear-gradient(45deg, #3b82f6, #8b5cf6) !important; + color: white !important; + text-decoration: none !important; + border-radius: 50px !important; + font-weight: 600 !important; + transition: all 0.3s ease !important; + border: none !important; + cursor: pointer !important; + font-size: 1rem !important; +} + +.btn-primary:hover, .btn:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 30px rgba(59, 130, 246, 0.3) !important; +} + +/* Карточки */ +.card-hover, .card { + transition: all 0.3s ease !important; + border-radius: 1rem !important; + overflow: hidden !important; + background: white !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; +} + +.card-hover:hover, .card:hover { + transform: translateY(-8px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Секции */ +section { + padding: 5rem 1rem !important; +} + +.container, .max-w-7xl { + max-width: 1200px !important; + margin: 0 auto !important; + padding-left: 1rem !important; + padding-right: 1rem !important; +} + +/* Грид системы */ +.grid { + display: grid !important; +} + +.grid-cols-1 { + grid-template-columns: 1fr !important; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, 1fr) !important; +} + +.grid-cols-3 { + grid-template-columns: repeat(3, 1fr) !important; +} + +.grid-cols-4 { + grid-template-columns: repeat(4, 1fr) !important; +} + +.gap-8 { + gap: 2rem !important; +} + +/* Заголовки */ +h1, h2, h3, h4, h5, h6 { + color: #1f2937 !important; + font-weight: 600 !important; +} + +h1 { + font-size: 3rem !important; +} + +h2 { + font-size: 2.5rem !important; +} + +h3 { + font-size: 1.75rem !important; +} + +/* Footer */ +footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 1rem 1rem !important; +} + +/* Отзывчивость */ +@media (max-width: 768px) { + .nav-links, .menu { + display: none !important; + } + + body { + padding-top: 60px !important; + } + + nav, .navigation { + height: 60px !important; + } + + .hero-section { + margin-top: -60px !important; + padding-top: 60px !important; + } + + section { + padding: 3rem 1rem !important; + } + + .hero-section h1 { + font-size: 2.5rem !important; + } + + .grid-cols-2, .grid-cols-3, .grid-cols-4 { + grid-template-columns: 1fr !important; + } +} + +/* Дополнительные утилитарные классы */ +.text-center { + text-align: center !important; +} + +.text-white { + color: white !important; +} + +.bg-white { + background-color: white !important; +} + +.rounded-lg { + border-radius: 0.5rem !important; +} + +.rounded-2xl { + border-radius: 1rem !important; +} + +.shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important; +} + +.mb-4 { + margin-bottom: 1rem !important; +} + +.mb-8 { + margin-bottom: 2rem !important; +} + +.p-8 { + padding: 2rem !important; +} + +.flex { + display: flex !important; +} + +.items-center { + align-items: center !important; +} + +.justify-center { + justify-content: center !important; +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/base_20251020225302.css b/.history/public/css/base_20251020225302.css new file mode 100644 index 0000000..0df34a4 --- /dev/null +++ b/.history/public/css/base_20251020225302.css @@ -0,0 +1,686 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Base CSS - Исправленные стили для главной страницы */ + +/* Reset и базовые стили */ +* { + box-sizing: border-box !important; + margin: 0 !important; + padding: 0 !important; +} + +html { + font-size: 16px !important; + scroll-behavior: smooth !important; +} + +body { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; + line-height: 1.6 !important; + color: #1f2937 !important; + background-color: #ffffff !important; + margin: 0 !important; + padding: 0 !important; + padding-top: 80px !important; /* Отступ для навигации */ +} + +/* Навигация - исправленная */ +nav, .navigation { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + -webkit-backdrop-filter: blur(20px) !important; + backdrop-filter: blur(20px) !important; + border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important; + height: 80px !important; + box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1) !important; +} + +.navbar, .nav-container { + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + padding: 0 2rem !important; + max-width: 1200px !important; + margin: 0 auto !important; + height: 100% !important; +} + +.logo, .brand { + font-size: 1.75rem !important; + font-weight: 800 !important; + color: #1d4ed8 !important; + text-decoration: none !important; + letter-spacing: -0.025em !important; +} + +.nav-links, .menu { + display: flex !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; + gap: 2.5rem !important; +} + +.nav-links li, .menu li { + margin: 0 !important; + padding: 0 !important; +} + +.nav-links a, .menu a { + color: #374151 !important; + text-decoration: none !important; + font-weight: 500 !important; + font-size: 0.95rem !important; + transition: all 0.3s ease !important; + padding: 0.75rem 0 !important; + position: relative !important; +} + +.nav-links a:hover, .menu a:hover { + color: #1d4ed8 !important; + transform: translateY(-1px) !important; +} + +.nav-links a::after, .menu a::after { + content: '' !important; + position: absolute !important; + bottom: 0.5rem !important; + left: 0 !important; + width: 0 !important; + height: 2px !important; + background: linear-gradient(45deg, #1d4ed8, #8b5cf6) !important; + transition: width 0.3s ease !important; +} + +.nav-links a:hover::after, .menu a:hover::after { + width: 100% !important; +} + +/* Hero секция - исправленная */ +.hero-section { + min-height: 100vh !important; + background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 25%, #312e81 50%, #7c3aed 75%, #3730a3 100%) !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + text-align: center !important; + color: white !important; + position: relative !important; + overflow: hidden !important; + margin-top: -80px !important; + padding-top: 80px !important; +} + +.hero-section::before { + content: '' !important; + position: absolute !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + background: radial-gradient(circle at 30% 40%, rgba(59, 130, 246, 0.3) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.3) 0%, transparent 50%), + radial-gradient(circle at 40% 80%, rgba(16, 185, 129, 0.2) 0%, transparent 50%) !important; + z-index: 1 !important; +} + +.hero-section > div { + position: relative !important; + z-index: 2 !important; +} + +.hero-section h1 { + font-size: 4rem !important; + font-weight: 800 !important; + margin-bottom: 1.5rem !important; + line-height: 1.1 !important; + letter-spacing: -0.025em !important; +} + +.hero-section p { + font-size: 1.35rem !important; + margin-bottom: 2.5rem !important; + opacity: 0.9 !important; + max-width: 600px !important; + margin-left: auto !important; + margin-right: auto !important; +} + +/* Кнопки - улучшенные */ +.btn-primary, .btn { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + padding: 1.25rem 2.5rem !important; + background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%) !important; + color: white !important; + text-decoration: none !important; + border-radius: 50px !important; + font-weight: 700 !important; + font-size: 1.1rem !important; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; + border: none !important; + cursor: pointer !important; + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3) !important; + position: relative !important; + overflow: hidden !important; +} + +.btn-primary:hover, .btn:hover { + transform: translateY(-3px) scale(1.05) !important; + box-shadow: 0 15px 35px rgba(59, 130, 246, 0.4) !important; + background: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%) !important; +} + +.btn-primary::before, .btn::before { + content: '' !important; + position: absolute !important; + top: 0 !important; + left: -100% !important; + width: 100% !important; + height: 100% !important; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent) !important; + transition: left 0.6s !important; +} + +.btn-primary:hover::before, .btn:hover::before { + left: 100% !important; +} + +/* Карточки - улучшенные */ +.card-hover, .card { + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; + border-radius: 1.5rem !important; + overflow: hidden !important; + background: white !important; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05) !important; + border: 1px solid rgba(0, 0, 0, 0.05) !important; +} + +.card-hover:hover, .card:hover { + transform: translateY(-12px) scale(1.02) !important; + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15) !important; + border-color: rgba(59, 130, 246, 0.2) !important; +} + +/* Секции */ +section { + padding: 6rem 1rem !important; + position: relative !important; +} + +.container, .max-w-7xl { + max-width: 1200px !important; + margin: 0 auto !important; + padding-left: 1rem !important; + padding-right: 1rem !important; +} + +/* Заголовки */ +h1, h2, h3, h4, h5, h6 { + color: #1f2937 !important; + font-weight: 700 !important; + line-height: 1.2 !important; +} + +h2 { + font-size: 2.75rem !important; + margin-bottom: 1rem !important; +} + +h3 { + font-size: 1.5rem !important; + margin-bottom: 0.75rem !important; +} + +/* Параграфы и текст */ +p { + color: #6b7280 !important; + line-height: 1.7 !important; + margin-bottom: 1rem !important; +} + +/* Утилитарные классы Tailwind - принудительные */ +.text-center { + text-align: center !important; +} + +.text-white { + color: white !important; +} + +.bg-white { + background-color: white !important; +} + +.bg-gray-50 { + background-color: #f9fafb !important; +} + +.rounded-lg { + border-radius: 0.5rem !important; +} + +.rounded-2xl { + border-radius: 1rem !important; +} + +.shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important; +} + +.mb-4 { + margin-bottom: 1rem !important; +} + +.mb-8 { + margin-bottom: 2rem !important; +} + +.p-8 { + padding: 2rem !important; +} + +.flex { + display: flex !important; +} + +.grid { + display: grid !important; +} + +.items-center { + align-items: center !important; +} + +.justify-center { + justify-content: center !important; +} + +/* Грид системы */ +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)) !important; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; +} + +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; +} + +.grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)) !important; +} + +.gap-8 { + gap: 2rem !important; +} + +/* Отзывчивость - улучшенная */ +@media (max-width: 1024px) { + .grid-cols-4 { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } + + .hero-section h1 { + font-size: 3.5rem !important; + } +} + +@media (max-width: 768px) { + .nav-links, .menu { + display: none !important; + } + + body { + padding-top: 60px !important; + } + + nav, .navigation { + height: 60px !important; + } + + .hero-section { + margin-top: -60px !important; + padding-top: 60px !important; + } + + section { + padding: 4rem 1rem !important; + } + + .hero-section h1 { + font-size: 2.75rem !important; + } + + .hero-section p { + font-size: 1.1rem !important; + } + + .grid-cols-2, .grid-cols-3, .grid-cols-4 { + grid-template-columns: repeat(1, minmax(0, 1fr)) !important; + } + + .btn-primary, .btn { + padding: 1rem 2rem !important; + font-size: 1rem !important; + } +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/base_20251020225419.css b/.history/public/css/base_20251020225419.css new file mode 100644 index 0000000..0df34a4 --- /dev/null +++ b/.history/public/css/base_20251020225419.css @@ -0,0 +1,686 @@ +/* SmartSolTech - Base Styles for Elements */ + +/* Ensure proper styling without Tailwind conflicts */ +.navbar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + backdrop-filter: blur(10px) !important; + border-bottom: 1px solid #e5e7eb !important; + padding: 1rem 0 !important; +} + +.navbar-brand { + font-size: 1.5rem !important; + font-weight: 700 !important; + color: #3B82F6 !important; + text-decoration: none !important; +} + +.navbar-nav { + display: flex !important; + align-items: center !important; + gap: 2rem !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; +} + +.nav-link { + color: #6b7280 !important; + text-decoration: none !important; + font-weight: 500 !important; + padding: 0.5rem 1rem !important; + border-radius: 0.5rem !important; + transition: all 0.3s ease !important; +} + +.nav-link:hover, +.nav-link.active { + color: #3B82F6 !important; + background-color: #eff6ff !important; +} + +/* Base CSS - Исправленные стили для главной страницы */ + +/* Reset и базовые стили */ +* { + box-sizing: border-box !important; + margin: 0 !important; + padding: 0 !important; +} + +html { + font-size: 16px !important; + scroll-behavior: smooth !important; +} + +body { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; + line-height: 1.6 !important; + color: #1f2937 !important; + background-color: #ffffff !important; + margin: 0 !important; + padding: 0 !important; + padding-top: 80px !important; /* Отступ для навигации */ +} + +/* Навигация - исправленная */ +nav, .navigation { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000 !important; + background: rgba(255, 255, 255, 0.95) !important; + -webkit-backdrop-filter: blur(20px) !important; + backdrop-filter: blur(20px) !important; + border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important; + height: 80px !important; + box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1) !important; +} + +.navbar, .nav-container { + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + padding: 0 2rem !important; + max-width: 1200px !important; + margin: 0 auto !important; + height: 100% !important; +} + +.logo, .brand { + font-size: 1.75rem !important; + font-weight: 800 !important; + color: #1d4ed8 !important; + text-decoration: none !important; + letter-spacing: -0.025em !important; +} + +.nav-links, .menu { + display: flex !important; + list-style: none !important; + margin: 0 !important; + padding: 0 !important; + gap: 2.5rem !important; +} + +.nav-links li, .menu li { + margin: 0 !important; + padding: 0 !important; +} + +.nav-links a, .menu a { + color: #374151 !important; + text-decoration: none !important; + font-weight: 500 !important; + font-size: 0.95rem !important; + transition: all 0.3s ease !important; + padding: 0.75rem 0 !important; + position: relative !important; +} + +.nav-links a:hover, .menu a:hover { + color: #1d4ed8 !important; + transform: translateY(-1px) !important; +} + +.nav-links a::after, .menu a::after { + content: '' !important; + position: absolute !important; + bottom: 0.5rem !important; + left: 0 !important; + width: 0 !important; + height: 2px !important; + background: linear-gradient(45deg, #1d4ed8, #8b5cf6) !important; + transition: width 0.3s ease !important; +} + +.nav-links a:hover::after, .menu a:hover::after { + width: 100% !important; +} + +/* Hero секция - исправленная */ +.hero-section { + min-height: 100vh !important; + background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 25%, #312e81 50%, #7c3aed 75%, #3730a3 100%) !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + text-align: center !important; + color: white !important; + position: relative !important; + overflow: hidden !important; + margin-top: -80px !important; + padding-top: 80px !important; +} + +.hero-section::before { + content: '' !important; + position: absolute !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + background: radial-gradient(circle at 30% 40%, rgba(59, 130, 246, 0.3) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.3) 0%, transparent 50%), + radial-gradient(circle at 40% 80%, rgba(16, 185, 129, 0.2) 0%, transparent 50%) !important; + z-index: 1 !important; +} + +.hero-section > div { + position: relative !important; + z-index: 2 !important; +} + +.hero-section h1 { + font-size: 4rem !important; + font-weight: 800 !important; + margin-bottom: 1.5rem !important; + line-height: 1.1 !important; + letter-spacing: -0.025em !important; +} + +.hero-section p { + font-size: 1.35rem !important; + margin-bottom: 2.5rem !important; + opacity: 0.9 !important; + max-width: 600px !important; + margin-left: auto !important; + margin-right: auto !important; +} + +/* Кнопки - улучшенные */ +.btn-primary, .btn { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + padding: 1.25rem 2.5rem !important; + background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%) !important; + color: white !important; + text-decoration: none !important; + border-radius: 50px !important; + font-weight: 700 !important; + font-size: 1.1rem !important; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; + border: none !important; + cursor: pointer !important; + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3) !important; + position: relative !important; + overflow: hidden !important; +} + +.btn-primary:hover, .btn:hover { + transform: translateY(-3px) scale(1.05) !important; + box-shadow: 0 15px 35px rgba(59, 130, 246, 0.4) !important; + background: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%) !important; +} + +.btn-primary::before, .btn::before { + content: '' !important; + position: absolute !important; + top: 0 !important; + left: -100% !important; + width: 100% !important; + height: 100% !important; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent) !important; + transition: left 0.6s !important; +} + +.btn-primary:hover::before, .btn:hover::before { + left: 100% !important; +} + +/* Карточки - улучшенные */ +.card-hover, .card { + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; + border-radius: 1.5rem !important; + overflow: hidden !important; + background: white !important; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05) !important; + border: 1px solid rgba(0, 0, 0, 0.05) !important; +} + +.card-hover:hover, .card:hover { + transform: translateY(-12px) scale(1.02) !important; + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15) !important; + border-color: rgba(59, 130, 246, 0.2) !important; +} + +/* Секции */ +section { + padding: 6rem 1rem !important; + position: relative !important; +} + +.container, .max-w-7xl { + max-width: 1200px !important; + margin: 0 auto !important; + padding-left: 1rem !important; + padding-right: 1rem !important; +} + +/* Заголовки */ +h1, h2, h3, h4, h5, h6 { + color: #1f2937 !important; + font-weight: 700 !important; + line-height: 1.2 !important; +} + +h2 { + font-size: 2.75rem !important; + margin-bottom: 1rem !important; +} + +h3 { + font-size: 1.5rem !important; + margin-bottom: 0.75rem !important; +} + +/* Параграфы и текст */ +p { + color: #6b7280 !important; + line-height: 1.7 !important; + margin-bottom: 1rem !important; +} + +/* Утилитарные классы Tailwind - принудительные */ +.text-center { + text-align: center !important; +} + +.text-white { + color: white !important; +} + +.bg-white { + background-color: white !important; +} + +.bg-gray-50 { + background-color: #f9fafb !important; +} + +.rounded-lg { + border-radius: 0.5rem !important; +} + +.rounded-2xl { + border-radius: 1rem !important; +} + +.shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important; +} + +.mb-4 { + margin-bottom: 1rem !important; +} + +.mb-8 { + margin-bottom: 2rem !important; +} + +.p-8 { + padding: 2rem !important; +} + +.flex { + display: flex !important; +} + +.grid { + display: grid !important; +} + +.items-center { + align-items: center !important; +} + +.justify-center { + justify-content: center !important; +} + +/* Грид системы */ +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)) !important; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; +} + +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; +} + +.grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)) !important; +} + +.gap-8 { + gap: 2rem !important; +} + +/* Отзывчивость - улучшенная */ +@media (max-width: 1024px) { + .grid-cols-4 { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } + + .hero-section h1 { + font-size: 3.5rem !important; + } +} + +@media (max-width: 768px) { + .nav-links, .menu { + display: none !important; + } + + body { + padding-top: 60px !important; + } + + nav, .navigation { + height: 60px !important; + } + + .hero-section { + margin-top: -60px !important; + padding-top: 60px !important; + } + + section { + padding: 4rem 1rem !important; + } + + .hero-section h1 { + font-size: 2.75rem !important; + } + + .hero-section p { + font-size: 1.1rem !important; + } + + .grid-cols-2, .grid-cols-3, .grid-cols-4 { + grid-template-columns: repeat(1, minmax(0, 1fr)) !important; + } + + .btn-primary, .btn { + padding: 1rem 2rem !important; + font-size: 1rem !important; + } +} + +.hero-title { + font-size: 3.5rem !important; + font-weight: 700 !important; + margin-bottom: 1rem !important; + line-height: 1.2 !important; +} + +.hero-subtitle { + font-size: 1.25rem !important; + margin-bottom: 2rem !important; + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Buttons */ +.btn { + display: inline-block !important; + padding: 0.75rem 1.5rem !important; + border-radius: 0.5rem !important; + text-decoration: none !important; + font-weight: 600 !important; + text-align: center !important; + border: none !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + font-size: 1rem !important; +} + +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8) !important; + color: white !important; +} + +.btn-primary:hover { + transform: translateY(-2px) !important; + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3) !important; +} + +.btn-secondary { + background: transparent !important; + color: white !important; + border: 2px solid white !important; +} + +.btn-secondary:hover { + background: white !important; + color: #3B82F6 !important; +} + +/* Cards */ +.card { + background: white !important; + border-radius: 1rem !important; + padding: 2rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.card:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +/* Sections */ +.section { + padding: 4rem 2rem !important; +} + +.section-title { + font-size: 2.5rem !important; + font-weight: 700 !important; + text-align: center !important; + margin-bottom: 1rem !important; + color: #1f2937 !important; +} + +.section-description { + font-size: 1.125rem !important; + text-align: center !important; + color: #6b7280 !important; + max-width: 600px !important; + margin: 0 auto 3rem !important; +} + +/* Container */ +.container { + max-width: 1200px !important; + margin: 0 auto !important; + padding: 0 1rem !important; +} + +/* Grid Layouts */ +.grid-2 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-3 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important; + gap: 2rem !important; +} + +.grid-4 { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important; + gap: 1.5rem !important; +} + +/* Language Selector */ +.language-selector { + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.language-selector a { + color: #6b7280 !important; + text-decoration: none !important; + padding: 0.25rem 0.5rem !important; + border-radius: 0.25rem !important; + font-size: 0.875rem !important; +} + +.language-selector a:hover { + color: #3B82F6 !important; + background-color: #f3f4f6 !important; +} + +/* Mobile Menu */ +.mobile-menu-button { + display: none !important; + background: none !important; + border: none !important; + font-size: 1.5rem !important; + color: #6b7280 !important; + cursor: pointer !important; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem !important; + } + + .mobile-menu-button { + display: block !important; + } + + .navbar-nav { + display: none !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + background: white !important; + flex-direction: column !important; + padding: 1rem !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important; + } + + .navbar-nav.show { + display: flex !important; + } + + .section { + padding: 2rem 1rem !important; + } + + .section-title { + font-size: 2rem !important; + } +} + +/* Footer */ +.footer { + background: #1f2937 !important; + color: white !important; + padding: 3rem 2rem 1rem !important; + text-align: center !important; +} + +.footer p { + color: #d1d5db !important; +} + +/* Service Icons */ +.service-icon { + width: 80px !important; + height: 80px !important; + background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; + border-radius: 50% !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 2rem !important; + color: white !important; + margin: 0 auto 1rem !important; +} + +/* Portfolio Items */ +.portfolio-item { + background: white !important; + border-radius: 1rem !important; + overflow: hidden !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important; + transition: all 0.3s ease !important; +} + +.portfolio-item:hover { + transform: translateY(-4px) !important; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1) !important; +} + +.portfolio-image { + width: 100% !important; + height: 200px !important; + object-fit: cover !important; + display: block !important; +} + +.portfolio-content { + padding: 1.5rem !important; +} + +.portfolio-title { + font-size: 1.25rem !important; + font-weight: 600 !important; + margin-bottom: 0.5rem !important; + color: #1f2937 !important; +} + +.portfolio-description { + color: #6b7280 !important; + margin-bottom: 1rem !important; +} + +/* Form Styles */ +.form-group { + margin-bottom: 1.5rem !important; +} + +.form-label { + display: block !important; + font-weight: 500 !important; + margin-bottom: 0.5rem !important; + color: #374151 !important; +} + +.form-input, +.form-textarea, +.form-select { + width: 100% !important; + padding: 0.75rem !important; + border: 2px solid #e5e7eb !important; + border-radius: 0.5rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + outline: none !important; + border-color: #3B82F6 !important; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important; +} \ No newline at end of file diff --git a/.history/public/css/dark-theme_20251020042230.css b/.history/public/css/dark-theme_20251020042230.css new file mode 100644 index 0000000..19d8f4f --- /dev/null +++ b/.history/public/css/dark-theme_20251020042230.css @@ -0,0 +1,315 @@ +/* Dark Theme Support for SmartSolTech */ + +/* Base Dark Theme */ +html.dark { + color-scheme: dark; +} + +.dark body { + background-color: #111827; + color: #f9fafb; +} + +/* Navigation Dark Theme */ +.dark nav { + background-color: #1f2937; + border-color: #374151; +} + +.dark .nav-link { + color: #d1d5db; +} + +.dark .nav-link:hover { + color: #60a5fa; +} + +.dark .nav-link.active { + color: #60a5fa; +} + +/* Sections Dark Theme */ +.dark section { + background-color: #111827; + color: #f9fafb; +} + +.dark .bg-white { + background-color: #1f2937 !important; +} + +.dark .bg-gray-50 { + background-color: #111827 !important; +} + +.dark .bg-gray-100 { + background-color: #374151 !important; +} + +.dark .bg-gray-900 { + background-color: #030712 !important; +} + +/* Text Colors Dark Theme */ +.dark .text-gray-900 { + color: #f9fafb !important; +} + +.dark .text-gray-800 { + color: #e5e7eb !important; +} + +.dark .text-gray-700 { + color: #d1d5db !important; +} + +.dark .text-gray-600 { + color: #9ca3af !important; +} + +.dark .text-gray-500 { + color: #6b7280 !important; +} + +.dark .text-gray-400 { + color: #9ca3af !important; +} + +.dark .text-gray-300 { + color: #d1d5db !important; +} + +/* Cards Dark Theme */ +.dark .card-hover { + background-color: #1f2937; + border-color: #374151; +} + +.dark .card-hover:hover { + background-color: #374151; + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5); +} + +/* Forms Dark Theme */ +.dark .form-input { + background-color: #374151; + border-color: #4b5563; + color: #f9fafb; +} + +.dark .form-input:focus { + border-color: #60a5fa; + background-color: #1f2937; +} + +.dark .form-input::placeholder { + color: #9ca3af; +} + +.dark input, +.dark textarea, +.dark select { + background-color: #374151; + border-color: #4b5563; + color: #f9fafb; +} + +.dark input:focus, +.dark textarea:focus, +.dark select:focus { + border-color: #60a5fa; + background-color: #1f2937; +} + +/* Borders Dark Theme */ +.dark .border-gray-300 { + border-color: #4b5563 !important; +} + +.dark .border-gray-200 { + border-color: #374151 !important; +} + +.dark .border-t { + border-color: #374151; +} + +/* Contact Form Dark Theme */ +.dark .contact-form { + background: linear-gradient(145deg, rgba(31,41,55,0.9), rgba(31,41,55,0.95)); + border-color: #374151; +} + +/* Service Cards Dark Theme */ +.dark .service-card { + background: linear-gradient(145deg, rgba(31,41,55,0.8), rgba(31,41,55,0.6)); + border-color: #374151; +} + +/* Team Cards Dark Theme */ +.dark .team-card { + background-color: #1f2937; + border-color: #374151; +} + +/* Portfolio Items Dark Theme */ +.dark .portfolio-item { + background-color: #1f2937; +} + +/* Hero Section Dark Theme */ +.dark .hero-section { + background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%); +} + +/* Shadows Dark Theme */ +.dark .shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2); +} + +.dark .shadow-xl { + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2); +} + +.dark .shadow-2xl { + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); +} + +/* Dropdown Dark Theme */ +.dark .dropdown-menu { + background-color: #1f2937; + border-color: #374151; +} + +.dark .dropdown-menu a { + color: #d1d5db; +} + +.dark .dropdown-menu a:hover { + background-color: #374151; + color: #f9fafb; +} + +/* Icons Dark Theme */ +.dark .text-blue-600 { + color: #60a5fa !important; +} + +.dark .text-purple-600 { + color: #a78bfa !important; +} + +.dark .text-green-600 { + color: #34d399 !important; +} + +.dark .text-yellow-600 { + color: #fbbf24 !important; +} + +/* Buttons Dark Theme */ +.dark .btn-primary { + background: linear-gradient(135deg, #3b82f6, #1d4ed8); +} + +.dark .btn-primary:hover { + background: linear-gradient(135deg, #1d4ed8, #1e40af); +} + +/* Footer Dark Theme */ +.dark footer { + background-color: #030712; + border-color: #1f2937; +} + +.dark .footer-gradient { + background: linear-gradient(135deg, #030712 0%, #111827 100%); +} + +/* Scrollbar Dark Theme */ +.dark ::-webkit-scrollbar-track { + background: #1f2937; +} + +.dark ::-webkit-scrollbar-thumb { + background: linear-gradient(135deg, #3b82f6, #1d4ed8); +} + +/* Technology Stack Dark Theme */ +.dark .tech-stack { + background-color: #030712; +} + +.dark .tech-card { + background-color: #1f2937; + border-color: #374151; +} + +/* CTA Section Dark Theme */ +.dark .cta-section { + background: linear-gradient(135deg, #1e40af 0%, #7c3aed 100%); +} + +/* Testimonials Dark Theme */ +.dark .testimonial-card { + background: rgba(31, 41, 55, 0.8); + border-color: #374151; +} + +/* Alert Messages Dark Theme */ +.dark .alert-success { + background: rgba(16, 185, 129, 0.1); + border-color: rgba(16, 185, 129, 0.3); + color: #10b981; +} + +.dark .alert-error { + background: rgba(239, 68, 68, 0.1); + border-color: rgba(239, 68, 68, 0.3); + color: #ef4444; +} + +/* Mobile Menu Dark Theme */ +.dark #mobile-menu { + background-color: #1f2937; + border-color: #374151; +} + +/* Language Dropdown Dark Theme */ +.dark #mobile-language-menu { + background-color: #1f2937; + border-color: #374151; +} + +/* Smooth Theme Transition */ +* { + transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; +} + +/* Print styles for dark theme */ +@media print { + .dark * { + background: white !important; + color: black !important; + } +} + +/* High contrast mode */ +@media (prefers-contrast: high) { + .dark { + color: white !important; + background-color: black !important; + } + + .dark .border { + border-width: 2px; + } +} + +/* Reduced motion for accessibility */ +@media (prefers-reduced-motion: reduce) { + .dark * { + transition: none !important; + animation: none !important; + } +} \ No newline at end of file diff --git a/.history/public/css/dark-theme_20251020042243.css b/.history/public/css/dark-theme_20251020042243.css new file mode 100644 index 0000000..19d8f4f --- /dev/null +++ b/.history/public/css/dark-theme_20251020042243.css @@ -0,0 +1,315 @@ +/* Dark Theme Support for SmartSolTech */ + +/* Base Dark Theme */ +html.dark { + color-scheme: dark; +} + +.dark body { + background-color: #111827; + color: #f9fafb; +} + +/* Navigation Dark Theme */ +.dark nav { + background-color: #1f2937; + border-color: #374151; +} + +.dark .nav-link { + color: #d1d5db; +} + +.dark .nav-link:hover { + color: #60a5fa; +} + +.dark .nav-link.active { + color: #60a5fa; +} + +/* Sections Dark Theme */ +.dark section { + background-color: #111827; + color: #f9fafb; +} + +.dark .bg-white { + background-color: #1f2937 !important; +} + +.dark .bg-gray-50 { + background-color: #111827 !important; +} + +.dark .bg-gray-100 { + background-color: #374151 !important; +} + +.dark .bg-gray-900 { + background-color: #030712 !important; +} + +/* Text Colors Dark Theme */ +.dark .text-gray-900 { + color: #f9fafb !important; +} + +.dark .text-gray-800 { + color: #e5e7eb !important; +} + +.dark .text-gray-700 { + color: #d1d5db !important; +} + +.dark .text-gray-600 { + color: #9ca3af !important; +} + +.dark .text-gray-500 { + color: #6b7280 !important; +} + +.dark .text-gray-400 { + color: #9ca3af !important; +} + +.dark .text-gray-300 { + color: #d1d5db !important; +} + +/* Cards Dark Theme */ +.dark .card-hover { + background-color: #1f2937; + border-color: #374151; +} + +.dark .card-hover:hover { + background-color: #374151; + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5); +} + +/* Forms Dark Theme */ +.dark .form-input { + background-color: #374151; + border-color: #4b5563; + color: #f9fafb; +} + +.dark .form-input:focus { + border-color: #60a5fa; + background-color: #1f2937; +} + +.dark .form-input::placeholder { + color: #9ca3af; +} + +.dark input, +.dark textarea, +.dark select { + background-color: #374151; + border-color: #4b5563; + color: #f9fafb; +} + +.dark input:focus, +.dark textarea:focus, +.dark select:focus { + border-color: #60a5fa; + background-color: #1f2937; +} + +/* Borders Dark Theme */ +.dark .border-gray-300 { + border-color: #4b5563 !important; +} + +.dark .border-gray-200 { + border-color: #374151 !important; +} + +.dark .border-t { + border-color: #374151; +} + +/* Contact Form Dark Theme */ +.dark .contact-form { + background: linear-gradient(145deg, rgba(31,41,55,0.9), rgba(31,41,55,0.95)); + border-color: #374151; +} + +/* Service Cards Dark Theme */ +.dark .service-card { + background: linear-gradient(145deg, rgba(31,41,55,0.8), rgba(31,41,55,0.6)); + border-color: #374151; +} + +/* Team Cards Dark Theme */ +.dark .team-card { + background-color: #1f2937; + border-color: #374151; +} + +/* Portfolio Items Dark Theme */ +.dark .portfolio-item { + background-color: #1f2937; +} + +/* Hero Section Dark Theme */ +.dark .hero-section { + background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%); +} + +/* Shadows Dark Theme */ +.dark .shadow-lg { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2); +} + +.dark .shadow-xl { + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2); +} + +.dark .shadow-2xl { + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); +} + +/* Dropdown Dark Theme */ +.dark .dropdown-menu { + background-color: #1f2937; + border-color: #374151; +} + +.dark .dropdown-menu a { + color: #d1d5db; +} + +.dark .dropdown-menu a:hover { + background-color: #374151; + color: #f9fafb; +} + +/* Icons Dark Theme */ +.dark .text-blue-600 { + color: #60a5fa !important; +} + +.dark .text-purple-600 { + color: #a78bfa !important; +} + +.dark .text-green-600 { + color: #34d399 !important; +} + +.dark .text-yellow-600 { + color: #fbbf24 !important; +} + +/* Buttons Dark Theme */ +.dark .btn-primary { + background: linear-gradient(135deg, #3b82f6, #1d4ed8); +} + +.dark .btn-primary:hover { + background: linear-gradient(135deg, #1d4ed8, #1e40af); +} + +/* Footer Dark Theme */ +.dark footer { + background-color: #030712; + border-color: #1f2937; +} + +.dark .footer-gradient { + background: linear-gradient(135deg, #030712 0%, #111827 100%); +} + +/* Scrollbar Dark Theme */ +.dark ::-webkit-scrollbar-track { + background: #1f2937; +} + +.dark ::-webkit-scrollbar-thumb { + background: linear-gradient(135deg, #3b82f6, #1d4ed8); +} + +/* Technology Stack Dark Theme */ +.dark .tech-stack { + background-color: #030712; +} + +.dark .tech-card { + background-color: #1f2937; + border-color: #374151; +} + +/* CTA Section Dark Theme */ +.dark .cta-section { + background: linear-gradient(135deg, #1e40af 0%, #7c3aed 100%); +} + +/* Testimonials Dark Theme */ +.dark .testimonial-card { + background: rgba(31, 41, 55, 0.8); + border-color: #374151; +} + +/* Alert Messages Dark Theme */ +.dark .alert-success { + background: rgba(16, 185, 129, 0.1); + border-color: rgba(16, 185, 129, 0.3); + color: #10b981; +} + +.dark .alert-error { + background: rgba(239, 68, 68, 0.1); + border-color: rgba(239, 68, 68, 0.3); + color: #ef4444; +} + +/* Mobile Menu Dark Theme */ +.dark #mobile-menu { + background-color: #1f2937; + border-color: #374151; +} + +/* Language Dropdown Dark Theme */ +.dark #mobile-language-menu { + background-color: #1f2937; + border-color: #374151; +} + +/* Smooth Theme Transition */ +* { + transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; +} + +/* Print styles for dark theme */ +@media print { + .dark * { + background: white !important; + color: black !important; + } +} + +/* High contrast mode */ +@media (prefers-contrast: high) { + .dark { + color: white !important; + background-color: black !important; + } + + .dark .border { + border-width: 2px; + } +} + +/* Reduced motion for accessibility */ +@media (prefers-reduced-motion: reduce) { + .dark * { + transition: none !important; + animation: none !important; + } +} \ No newline at end of file diff --git a/.history/public/css/fixes_20251021185301.css b/.history/public/css/fixes_20251021185301.css new file mode 100644 index 0000000..d161529 --- /dev/null +++ b/.history/public/css/fixes_20251021185301.css @@ -0,0 +1,310 @@ +/* SmartSolTech - Design Fixes & Enhancements */ + +/* Glass effect improvements */ +.glass-effect { + background: rgba(255, 255, 255, 0.15); + border: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + /* Fallback for browsers that don't support backdrop-filter */ +} + +/* Support backdrop-filter for modern browsers */ +@supports (backdrop-filter: blur(10px)) { + .glass-effect { + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + } +} + +/* Hero section improvements */ +.hero-section { + position: relative; + overflow: hidden; + min-height: 100vh; +} + +/* Background blob animations */ +@keyframes blob { + 0% { transform: translate(0px, 0px) scale(1); } + 33% { transform: translate(30px, -50px) scale(1.1); } + 66% { transform: translate(-20px, 20px) scale(0.9); } + 100% { transform: translate(0px, 0px) scale(1); } +} + +.animate-blob { + animation: blob 7s infinite; +} + +.animation-delay-2000 { + animation-delay: 2s; +} + +.animation-delay-4000 { + animation-delay: 4s; +} + +/* Enhanced card hover effects */ +.card-hover { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + backface-visibility: hidden; +} + +.card-hover:hover { + transform: translateY(-8px) scale(1.02); + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15); +} + +/* Portfolio item enhancements */ +.portfolio-item { + overflow: hidden; + border-radius: 16px; + position: relative; +} + +.portfolio-image { + transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1); +} + +.portfolio-item:hover .portfolio-image { + transform: scale(1.1); +} + +/* Button improvements */ +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8); + border: none; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.btn-primary::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.5s; +} + +.btn-primary:hover::before { + left: 100%; +} + +.btn-primary:hover { + background: linear-gradient(135deg, #1D4ED8, #1E40AF); + transform: translateY(-3px); + box-shadow: 0 15px 35px rgba(59, 130, 246, 0.4); +} + +/* Navigation improvements */ +.nav-link { + position: relative; + transition: all 0.3s ease; +} + +.nav-link::after { + content: ''; + position: absolute; + bottom: -2px; + left: 50%; + width: 0; + height: 2px; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + transition: all 0.3s ease; + transform: translateX(-50%); +} + +.nav-link:hover::after, +.nav-link.active::after { + width: 100%; +} + +/* Form improvements */ +.form-input { + transition: all 0.3s ease; + border: 2px solid #E5E7EB; + background: rgba(255, 255, 255, 0.95); +} + +.form-input:focus { + border-color: #3B82F6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); + transform: translateY(-1px); +} + +/* Contact form styling */ +.contact-form { + background: linear-gradient(145deg, rgba(255,255,255,0.9), rgba(255,255,255,0.95)); + border: 1px solid rgba(255,255,255,0.3); + box-shadow: 0 20px 40px rgba(0,0,0,0.1); +} + +/* CTA section improvements */ +.cta-section { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + position: relative; +} + +.cta-section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('data:image/svg+xml,'); + opacity: 0.3; +} + +/* Service cards */ +.service-card { + background: linear-gradient(145deg, rgba(255,255,255,0.1), rgba(255,255,255,0.05)); + border: 1px solid rgba(255,255,255,0.2); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +/* Team member cards */ +.team-card { + transition: all 0.3s ease; + background: rgba(255, 255, 255, 0.95); +} + +.team-card:hover { + transform: translateY(-10px); + box-shadow: 0 30px 60px rgba(0,0,0,0.12); +} + +/* Technology icons */ +.tech-icon { + transition: all 0.3s ease; +} + +.tech-icon:hover { + transform: scale(1.1) rotate(5deg); + filter: brightness(1.2); +} + +/* Loading states */ +.loading { + opacity: 0.7; + pointer-events: none; +} + +.loading::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + margin: -10px 0 0 -10px; + border: 2px solid #f3f3f3; + border-top: 2px solid #3B82F6; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Mobile optimizations */ +@media (max-width: 768px) { + .card-hover:hover { + transform: translateY(-4px) scale(1.01); + } + + .btn-primary:hover { + transform: translateY(-2px); + } + + .hero-section { + min-height: 80vh; + } + + .portfolio-item:hover .portfolio-image { + transform: scale(1.05); + } +} + +/* Accessibility improvements */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +button:focus, +input:focus, +textarea:focus, +select:focus, +a:focus { + outline: 2px solid #3B82F6; + outline-offset: 2px; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Print styles */ +@media print { + .no-print { + display: none !important; + } + + body { + color: black !important; + background: white !important; + } +} + +/* iOS Style Theme Toggle */ +.theme-toggle-slider { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* Theme toggle background states */ +input#theme-toggle:checked + label > div { + background-color: #4F46E5 !important; +} + +input#theme-toggle + label > div { + background-color: #D1D5DB; +} + +/* Dark mode adjustments for toggle */ +.dark input#theme-toggle + label > div { + background-color: #374151; +} + +.dark input#theme-toggle:checked + label > div { + background-color: #6366F1 !important; +} + +/* Smooth transitions for icons */ +.theme-sun-icon, +.theme-moon-icon { + transition: opacity 0.3s ease; +} + +/* Dark mode support (if needed) */ +@media (prefers-color-scheme: dark) { + .auto-dark { + color: #f9fafb; + background-color: #111827; + } +} \ No newline at end of file diff --git a/.history/public/css/fixes_20251021190951.css b/.history/public/css/fixes_20251021190951.css new file mode 100644 index 0000000..d161529 --- /dev/null +++ b/.history/public/css/fixes_20251021190951.css @@ -0,0 +1,310 @@ +/* SmartSolTech - Design Fixes & Enhancements */ + +/* Glass effect improvements */ +.glass-effect { + background: rgba(255, 255, 255, 0.15); + border: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + /* Fallback for browsers that don't support backdrop-filter */ +} + +/* Support backdrop-filter for modern browsers */ +@supports (backdrop-filter: blur(10px)) { + .glass-effect { + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + } +} + +/* Hero section improvements */ +.hero-section { + position: relative; + overflow: hidden; + min-height: 100vh; +} + +/* Background blob animations */ +@keyframes blob { + 0% { transform: translate(0px, 0px) scale(1); } + 33% { transform: translate(30px, -50px) scale(1.1); } + 66% { transform: translate(-20px, 20px) scale(0.9); } + 100% { transform: translate(0px, 0px) scale(1); } +} + +.animate-blob { + animation: blob 7s infinite; +} + +.animation-delay-2000 { + animation-delay: 2s; +} + +.animation-delay-4000 { + animation-delay: 4s; +} + +/* Enhanced card hover effects */ +.card-hover { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + backface-visibility: hidden; +} + +.card-hover:hover { + transform: translateY(-8px) scale(1.02); + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15); +} + +/* Portfolio item enhancements */ +.portfolio-item { + overflow: hidden; + border-radius: 16px; + position: relative; +} + +.portfolio-image { + transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1); +} + +.portfolio-item:hover .portfolio-image { + transform: scale(1.1); +} + +/* Button improvements */ +.btn-primary { + background: linear-gradient(135deg, #3B82F6, #1D4ED8); + border: none; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.btn-primary::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.5s; +} + +.btn-primary:hover::before { + left: 100%; +} + +.btn-primary:hover { + background: linear-gradient(135deg, #1D4ED8, #1E40AF); + transform: translateY(-3px); + box-shadow: 0 15px 35px rgba(59, 130, 246, 0.4); +} + +/* Navigation improvements */ +.nav-link { + position: relative; + transition: all 0.3s ease; +} + +.nav-link::after { + content: ''; + position: absolute; + bottom: -2px; + left: 50%; + width: 0; + height: 2px; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + transition: all 0.3s ease; + transform: translateX(-50%); +} + +.nav-link:hover::after, +.nav-link.active::after { + width: 100%; +} + +/* Form improvements */ +.form-input { + transition: all 0.3s ease; + border: 2px solid #E5E7EB; + background: rgba(255, 255, 255, 0.95); +} + +.form-input:focus { + border-color: #3B82F6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); + transform: translateY(-1px); +} + +/* Contact form styling */ +.contact-form { + background: linear-gradient(145deg, rgba(255,255,255,0.9), rgba(255,255,255,0.95)); + border: 1px solid rgba(255,255,255,0.3); + box-shadow: 0 20px 40px rgba(0,0,0,0.1); +} + +/* CTA section improvements */ +.cta-section { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + position: relative; +} + +.cta-section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('data:image/svg+xml,'); + opacity: 0.3; +} + +/* Service cards */ +.service-card { + background: linear-gradient(145deg, rgba(255,255,255,0.1), rgba(255,255,255,0.05)); + border: 1px solid rgba(255,255,255,0.2); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +/* Team member cards */ +.team-card { + transition: all 0.3s ease; + background: rgba(255, 255, 255, 0.95); +} + +.team-card:hover { + transform: translateY(-10px); + box-shadow: 0 30px 60px rgba(0,0,0,0.12); +} + +/* Technology icons */ +.tech-icon { + transition: all 0.3s ease; +} + +.tech-icon:hover { + transform: scale(1.1) rotate(5deg); + filter: brightness(1.2); +} + +/* Loading states */ +.loading { + opacity: 0.7; + pointer-events: none; +} + +.loading::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + margin: -10px 0 0 -10px; + border: 2px solid #f3f3f3; + border-top: 2px solid #3B82F6; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Mobile optimizations */ +@media (max-width: 768px) { + .card-hover:hover { + transform: translateY(-4px) scale(1.01); + } + + .btn-primary:hover { + transform: translateY(-2px); + } + + .hero-section { + min-height: 80vh; + } + + .portfolio-item:hover .portfolio-image { + transform: scale(1.05); + } +} + +/* Accessibility improvements */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +button:focus, +input:focus, +textarea:focus, +select:focus, +a:focus { + outline: 2px solid #3B82F6; + outline-offset: 2px; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Print styles */ +@media print { + .no-print { + display: none !important; + } + + body { + color: black !important; + background: white !important; + } +} + +/* iOS Style Theme Toggle */ +.theme-toggle-slider { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* Theme toggle background states */ +input#theme-toggle:checked + label > div { + background-color: #4F46E5 !important; +} + +input#theme-toggle + label > div { + background-color: #D1D5DB; +} + +/* Dark mode adjustments for toggle */ +.dark input#theme-toggle + label > div { + background-color: #374151; +} + +.dark input#theme-toggle:checked + label > div { + background-color: #6366F1 !important; +} + +/* Smooth transitions for icons */ +.theme-sun-icon, +.theme-moon-icon { + transition: opacity 0.3s ease; +} + +/* Dark mode support (if needed) */ +@media (prefers-color-scheme: dark) { + .auto-dark { + color: #f9fafb; + background-color: #111827; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020042218.css b/.history/public/css/main_20251020042218.css new file mode 100644 index 0000000..815736f --- /dev/null +++ b/.history/public/css/main_20251020042218.css @@ -0,0 +1,554 @@ +/* SmartSolTech - Main Styles */ + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020042243.css b/.history/public/css/main_20251020042243.css new file mode 100644 index 0000000..815736f --- /dev/null +++ b/.history/public/css/main_20251020042243.css @@ -0,0 +1,554 @@ +/* SmartSolTech - Main Styles */ + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020045321.css b/.history/public/css/main_20251020045321.css new file mode 100644 index 0000000..4026b93 --- /dev/null +++ b/.history/public/css/main_20251020045321.css @@ -0,0 +1,570 @@ +/* SmartSolTech - Main Styles */ + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; + background-color: #ffffff; +} + +/* Root Variables */ +:root { + --primary-color: #3B82F6; + --secondary-color: #8B5CF6; + --accent-color: #10B981; + --text-dark: #1f2937; + --text-light: #6b7280; + --bg-light: #f9fafb; + --border-color: #e5e7eb; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020045323.css b/.history/public/css/main_20251020045323.css new file mode 100644 index 0000000..4026b93 --- /dev/null +++ b/.history/public/css/main_20251020045323.css @@ -0,0 +1,570 @@ +/* SmartSolTech - Main Styles */ + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; + background-color: #ffffff; +} + +/* Root Variables */ +:root { + --primary-color: #3B82F6; + --secondary-color: #8B5CF6; + --accent-color: #10B981; + --text-dark: #1f2937; + --text-light: #6b7280; + --bg-light: #f9fafb; + --border-color: #e5e7eb; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020045335.css b/.history/public/css/main_20251020045335.css new file mode 100644 index 0000000..d45d96e --- /dev/null +++ b/.history/public/css/main_20251020045335.css @@ -0,0 +1,573 @@ +/* SmartSolTech - Main Styles */ + +/* Tailwind Base (if not loading properly) */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; + background-color: #ffffff; +} + +/* Root Variables */ +:root { + --primary-color: #3B82F6; + --secondary-color: #8B5CF6; + --accent-color: #10B981; + --text-dark: #1f2937; + --text-light: #6b7280; + --bg-light: #f9fafb; + --border-color: #e5e7eb; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020045359.css b/.history/public/css/main_20251020045359.css new file mode 100644 index 0000000..d45d96e --- /dev/null +++ b/.history/public/css/main_20251020045359.css @@ -0,0 +1,573 @@ +/* SmartSolTech - Main Styles */ + +/* Tailwind Base (if not loading properly) */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; + background-color: #ffffff; +} + +/* Root Variables */ +:root { + --primary-color: #3B82F6; + --secondary-color: #8B5CF6; + --accent-color: #10B981; + --text-dark: #1f2937; + --text-light: #6b7280; + --bg-light: #f9fafb; + --border-color: #e5e7eb; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/.history/public/css/main_20251020225556.css b/.history/public/css/main_20251020225556.css new file mode 100644 index 0000000..8858763 --- /dev/null +++ b/.history/public/css/main_20251020225556.css @@ -0,0 +1,606 @@ +/* SmartSolTech - Main Styles */ + +/* Tailwind Base (if not loading properly) */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; + background-color: #ffffff; +} + +/* Root Variables */ +:root { + --primary-color: #3B82F6; + --secondary-color: #8B5CF6; + --accent-color: #10B981; + --text-dark: #1f2937; + --text-light: #6b7280; + --bg-light: #f9fafb; + --border-color: #e5e7eb; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2rem; + } +} + +/* Hero секции - компактные для внутренних страниц */ +.hero-section-compact { + min-height: 40vh !important; + max-height: 50vh !important; + padding: 4rem 0 !important; +} + +.hero-section-compact h1 { + font-size: 3rem !important; + margin-bottom: 1rem !important; +} + +.hero-section-compact p { + font-size: 1.125rem !important; + opacity: 0.9 !important; +} + +@media (max-width: 768px) { + .hero-section-compact { + min-height: 30vh !important; + padding: 3rem 0 !important; + } + + .hero-section-compact h1 { + font-size: 2.5rem !important; + } +} + +/* Полноэкранный Hero только для главной */ +.hero-section { + min-height: 100vh !important; +} \ No newline at end of file diff --git a/.history/public/css/main_20251020225722.css b/.history/public/css/main_20251020225722.css new file mode 100644 index 0000000..8858763 --- /dev/null +++ b/.history/public/css/main_20251020225722.css @@ -0,0 +1,606 @@ +/* SmartSolTech - Main Styles */ + +/* Tailwind Base (if not loading properly) */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); + +/* CSS Reset and Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #1f2937; + background-color: #ffffff; +} + +/* Root Variables */ +:root { + --primary-color: #3B82F6; + --secondary-color: #8B5CF6; + --accent-color: #10B981; + --text-dark: #1f2937; + --text-light: #6b7280; + --bg-light: #f9fafb; + --border-color: #e5e7eb; +} + +/* Utility Classes */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.section-padding { + padding: 4rem 0; +} + +/* Navigation */ +.navbar { + background: rgba(255, 255, 255, 0.95); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: all 0.3s ease; +} + +.navbar-brand { + font-size: 1.5rem; + font-weight: bold; + color: #3b82f6; + text-decoration: none; +} + +.navbar-nav { + display: flex; + gap: 2rem; + list-style: none; +} + +.nav-link { + color: #6b7280; + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + transition: all 0.3s ease; +} + +.nav-link:hover, +.nav-link.active { + color: #3b82f6; + background-color: #eff6ff; +} + +.mobile-menu { + overflow: hidden; +} + +.mobile-menu.show { + max-height: 500px; +} + +/* Button Hover Effects */ +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + transition: all 0.3s ease; + transform: translateY(0); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3); +} + +/* Card Hover Effects */ +.card-hover { + transition: all 0.3s ease; + transform: translateY(0); +} + +.card-hover:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +/* Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.portfolio-item { + border-radius: 1rem; + overflow: hidden; + background: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; +} + +.portfolio-item:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); +} + +.portfolio-image { + position: relative; + overflow: hidden; + aspect-ratio: 16/10; +} + +.portfolio-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.portfolio-item:hover .portfolio-image img { + transform: scale(1.05); +} + +.portfolio-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(139, 92, 246, 0.8)); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.portfolio-item:hover .portfolio-overlay { + opacity: 1; +} + +/* Service Cards */ +.service-card { + background: white; + border-radius: 1rem; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.service-card:hover { + border-color: var(--primary-color); + transform: translateY(-4px); + box-shadow: 0 20px 40px rgba(59, 130, 246, 0.1); +} + +.service-icon { + width: 80px; + height: 80px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1rem; + font-size: 2rem; + color: white; + transition: all 0.3s ease; +} + +.service-card:hover .service-icon { + transform: scale(1.1) rotate(5deg); +} + +/* Contact Form */ +.contact-form { + background: white; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-control { + width: 100%; + padding: 1rem; + border: 2px solid var(--border-color); + border-radius: 0.5rem; + font-size: 1rem; + transition: all 0.3s ease; + background: white; +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Calculator Styles */ +.calculator-step { + animation: fadeIn 0.5s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.option-card { + border: 2px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + cursor: pointer; + transition: all 0.3s ease; + background: white; +} + +.option-card:hover { + border-color: var(--primary-color); + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.option-card.selected { + border-color: var(--primary-color); + background: rgba(59, 130, 246, 0.05); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--border-color); + border-radius: 4px; + overflow: hidden; + margin-bottom: 2rem; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); + transition: width 0.3s ease; +} + +/* Hero Section Animations */ +.hero-content { + animation: heroFadeIn 1s ease-out; +} + +@keyframes heroFadeIn { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Parallax Effect */ +.parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* Scroll Animations */ +.fade-in-up { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.fade-in-up.animate { + opacity: 1; + transform: translateY(0); +} + +/* Typography */ +.gradient-text { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Status Badges */ +.status-badge { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-new { + background: rgba(239, 68, 68, 0.1); + color: #dc2626; +} + +.status-in-progress { + background: rgba(245, 158, 11, 0.1); + color: #d97706; +} + +.status-completed { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .portfolio-grid { + grid-template-columns: 1fr; + } + + .hero-title { + font-size: 2.5rem; + } + + .service-card { + padding: 1.5rem; + } + + .calculator-step { + padding: 1rem; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --text-dark: #f9fafb; + --text-light: #d1d5db; + --bg-light: #1f2937; + --border-color: #374151; + } + + body { + background-color: #111827; + color: var(--text-dark); + } + + .card-hover, .service-card, .contact-form, .option-card { + background: #1f2937; + border-color: var(--border-color); + } + + .form-control { + background: #374151; + border-color: #4b5563; + color: white; + } + + .form-control:focus { + border-color: var(--primary-color); + } +} + +/* Print Styles */ +@media print { + .navbar, .footer, .contact-form, .mobile-menu { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.5; + } + + .portfolio-item, .service-card { + break-inside: avoid; + margin-bottom: 1rem; + } +} + +/* Accessibility */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Focus styles for better accessibility */ +.form-control:focus, +.btn:focus, +.option-card:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Loading States */ +.btn-loading { + position: relative; + color: transparent; +} + +.btn-loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-left: -8px; + margin-top: -8px; + border: 2px solid transparent; + border-top-color: currentColor; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +/* Calculator Styles */ +.calculator-step { + display: none; +} + +.calculator-step.active { + display: block; +} + +.service-option, +.complexity-option, +.timeline-option { + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} + +.service-option:hover, +.complexity-option:hover, +.timeline-option:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected, +.complexity-option.selected, +.timeline-option.selected { + border-color: #3B82F6 !important; + background-color: #EBF8FF !important; + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +.service-option.selected::after, +.complexity-option.selected::after, +.timeline-option.selected::after { + content: '✓'; + position: absolute; + top: 0.5rem; + right: 0.5rem; + width: 24px; + height: 24px; + background: #3B82F6; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; +} + +/* Price Display Animation */ +#final-price { + animation: priceReveal 0.8s ease-in-out; +} + +@keyframes priceReveal { + 0% { + opacity: 0; + transform: scale(0.8); + } + 50% { + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +/* Calculator Progress Bar */ +.calculator-progress { + width: 100%; + height: 4px; + background: #e5e7eb; + border-radius: 2px; + margin-bottom: 2rem; + overflow: hidden; +} + +.calculator-progress-bar { + height: 100%; + background: linear-gradient(90deg, #3B82F6, #8B5CF6); + border-radius: 2px; + transition: width 0.3s ease; + width: 33.33%; +} + +.calculator-progress-bar.step-2 { + width: 66.66%; +} + +.calculator-progress-bar.step-3 { + width: 100%; +} + +/* Calculator Mobile Improvements */ +@media (max-width: 768px) { + .service-option, + .complexity-option, + .timeline-option { + margin-bottom: 1rem; + } + + #final-price { + font-size: 2rem; + } +} + +/* Hero секции - компактные для внутренних страниц */ +.hero-section-compact { + min-height: 40vh !important; + max-height: 50vh !important; + padding: 4rem 0 !important; +} + +.hero-section-compact h1 { + font-size: 3rem !important; + margin-bottom: 1rem !important; +} + +.hero-section-compact p { + font-size: 1.125rem !important; + opacity: 0.9 !important; +} + +@media (max-width: 768px) { + .hero-section-compact { + min-height: 30vh !important; + padding: 3rem 0 !important; + } + + .hero-section-compact h1 { + font-size: 2.5rem !important; + } +} + +/* Полноэкранный Hero только для главной */ +.hero-section { + min-height: 100vh !important; +} \ No newline at end of file diff --git a/.history/public/images/icon-144x144_20251020042420.png b/.history/public/images/icon-144x144_20251020042420.png new file mode 100644 index 0000000..6edd642 --- /dev/null +++ b/.history/public/images/icon-144x144_20251020042420.png @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/icon-144x144_20251020042429.png b/.history/public/images/icon-144x144_20251020042429.png new file mode 100644 index 0000000..6edd642 --- /dev/null +++ b/.history/public/images/icon-144x144_20251020042429.png @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/icons/icon-192x192_20251020041929.png b/.history/public/images/icons/icon-192x192_20251020041929.png new file mode 100644 index 0000000..6d2ce2b --- /dev/null +++ b/.history/public/images/icons/icon-192x192_20251020041929.png @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/icons/icon-192x192_20251020041934.png b/.history/public/images/icons/icon-192x192_20251020041934.png new file mode 100644 index 0000000..6d2ce2b --- /dev/null +++ b/.history/public/images/icons/icon-192x192_20251020041934.png @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/logo_20251020041922.png b/.history/public/images/logo_20251020041922.png new file mode 100644 index 0000000..4054628 --- /dev/null +++ b/.history/public/images/logo_20251020041922.png @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/logo_20251020041933.png b/.history/public/images/logo_20251020041933.png new file mode 100644 index 0000000..4054628 --- /dev/null +++ b/.history/public/images/logo_20251020041933.png @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/portfolio/corporate-1_20251020041915.jpg b/.history/public/images/portfolio/corporate-1_20251020041915.jpg new file mode 100644 index 0000000..5649601 --- /dev/null +++ b/.history/public/images/portfolio/corporate-1_20251020041915.jpg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/portfolio/corporate-1_20251020041933.jpg b/.history/public/images/portfolio/corporate-1_20251020041933.jpg new file mode 100644 index 0000000..5649601 --- /dev/null +++ b/.history/public/images/portfolio/corporate-1_20251020041933.jpg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/portfolio/ecommerce-1_20251020041900.jpg b/.history/public/images/portfolio/ecommerce-1_20251020041900.jpg new file mode 100644 index 0000000..559feb7 --- /dev/null +++ b/.history/public/images/portfolio/ecommerce-1_20251020041900.jpg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/portfolio/ecommerce-1_20251020041933.jpg b/.history/public/images/portfolio/ecommerce-1_20251020041933.jpg new file mode 100644 index 0000000..559feb7 --- /dev/null +++ b/.history/public/images/portfolio/ecommerce-1_20251020041933.jpg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/portfolio/fitness-1_20251020041907.jpg b/.history/public/images/portfolio/fitness-1_20251020041907.jpg new file mode 100644 index 0000000..70126d4 --- /dev/null +++ b/.history/public/images/portfolio/fitness-1_20251020041907.jpg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/images/portfolio/fitness-1_20251020041933.jpg b/.history/public/images/portfolio/fitness-1_20251020041933.jpg new file mode 100644 index 0000000..70126d4 --- /dev/null +++ b/.history/public/images/portfolio/fitness-1_20251020041933.jpg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.history/public/sw_20251020042616.js b/.history/public/sw_20251020042616.js new file mode 100644 index 0000000..adeb970 --- /dev/null +++ b/.history/public/sw_20251020042616.js @@ -0,0 +1,399 @@ +// Service Worker for SmartSolTech PWA +const CACHE_NAME = 'smartsoltech-v1.0.0'; +const STATIC_CACHE_NAME = 'smartsoltech-static-v1.0.0'; +const DYNAMIC_CACHE_NAME = 'smartsoltech-dynamic-v1.0.0'; + +// Files to cache immediately +const STATIC_FILES = [ + '/', + '/css/main.css', + '/css/fixes.css', + '/css/dark-theme.css', + '/js/main.js', + '/images/logo.png', + '/images/icon-192x192.png', + '/images/icon-144x144.png', + '/manifest.json', + 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', + 'https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.js' +]; + +// Routes to cache dynamically +const DYNAMIC_ROUTES = [ + '/about', + '/services', + '/portfolio', + '/calculator', + '/contact' +]; + +// API endpoints to cache +const API_CACHE_PATTERNS = [ + /^\/api\/portfolio/, + /^\/api\/services/, + /^\/api\/calculator\/services/ +]; + +// Install event - cache static files +self.addEventListener('install', event => { + console.log('Service Worker: Installing...'); + + event.waitUntil( + caches.open(STATIC_CACHE_NAME) + .then(cache => { + console.log('Service Worker: Caching static files'); + return cache.addAll(STATIC_FILES); + }) + .then(() => { + console.log('Service Worker: Static files cached'); + return self.skipWaiting(); + }) + .catch(error => { + console.error('Service Worker: Error caching static files', error); + }) + ); +}); + +// Activate event - clean up old caches +self.addEventListener('activate', event => { + console.log('Service Worker: Activating...'); + + event.waitUntil( + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== STATIC_CACHE_NAME && + cacheName !== DYNAMIC_CACHE_NAME) { + console.log('Service Worker: Deleting old cache', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + .then(() => { + console.log('Service Worker: Activated'); + return self.clients.claim(); + }) + ); +}); + +// Fetch event - serve cached files or fetch from network +self.addEventListener('fetch', event => { + const request = event.request; + const url = new URL(request.url); + + // Skip non-GET requests + if (request.method !== 'GET') { + return; + } + + // Skip Chrome extension requests + if (url.protocol === 'chrome-extension:') { + return; + } + + // Handle different types of requests + if (isStaticFile(request.url)) { + event.respondWith(cacheFirst(request)); + } else if (isAPIRequest(request.url)) { + event.respondWith(networkFirst(request)); + } else if (isDynamicRoute(request.url)) { + event.respondWith(staleWhileRevalidate(request)); + } else { + event.respondWith(networkFirst(request)); + } +}); + +// Cache strategies +async function cacheFirst(request) { + try { + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + const networkResponse = await fetch(request); + const cache = await caches.open(STATIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + return networkResponse; + } catch (error) { + console.error('Cache first strategy failed:', error); + return new Response('Offline', { status: 503 }); + } +} + +async function networkFirst(request) { + try { + const networkResponse = await fetch(request); + + // Cache successful responses + if (networkResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + } + + return networkResponse; + } catch (error) { + console.log('Network first: Falling back to cache for', request.url); + + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + // Return offline page for navigation requests + if (request.mode === 'navigate') { + return caches.match('/offline.html') || new Response('Offline', { + status: 503, + headers: { 'Content-Type': 'text/html' } + }); + } + + return new Response('Network Error', { status: 503 }); + } +} + +async function staleWhileRevalidate(request) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const cachedResponse = await cache.match(request); + + const fetchPromise = fetch(request).then(networkResponse => { + if (networkResponse.ok) { + cache.put(request, networkResponse.clone()); + } + return networkResponse; + }); + + return cachedResponse || fetchPromise; +} + +// Helper functions +function isStaticFile(url) { + return url.includes('/css/') || + url.includes('/js/') || + url.includes('/images/') || + url.includes('/fonts/') || + url.includes('googleapis.com') || + url.includes('cdnjs.cloudflare.com'); +} + +function isAPIRequest(url) { + return url.includes('/api/') || + API_CACHE_PATTERNS.some(pattern => pattern.test(url)); +} + +function isDynamicRoute(url) { + const pathname = new URL(url).pathname; + return DYNAMIC_ROUTES.includes(pathname) || + pathname.startsWith('/portfolio/') || + pathname.startsWith('/services/'); +} + +// Background sync for form submissions +self.addEventListener('sync', event => { + console.log('Service Worker: Background sync triggered', event.tag); + + if (event.tag === 'contact-form-sync') { + event.waitUntil(syncContactForms()); + } +}); + +async function syncContactForms() { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const requests = await cache.keys(); + + const contactRequests = requests.filter(request => + request.url.includes('/api/contact/submit') + ); + + for (const request of contactRequests) { + try { + await fetch(request); + await cache.delete(request); + console.log('Contact form synced successfully'); + } catch (error) { + console.error('Failed to sync contact form:', error); + } + } + } catch (error) { + console.error('Background sync failed:', error); + } +} + +// Push notification handling +self.addEventListener('push', event => { + console.log('Service Worker: Push received', event); + + let data = {}; + if (event.data) { + data = event.data.json(); + } + + const title = data.title || 'SmartSolTech'; + const options = { + body: data.body || 'You have a new notification', + icon: '/images/icon-192x192.png', + badge: '/images/icon-72x72.png', + tag: data.tag || 'default', + data: data.url || '/', + actions: [ + { + action: 'open', + title: '열기', + icon: '/images/icon-open.png' + }, + { + action: 'close', + title: '닫기', + icon: '/images/icon-close.png' + } + ], + requireInteraction: data.requireInteraction || false, + silent: data.silent || false, + vibrate: data.vibrate || [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification(title, options) + ); +}); + +// Notification click handling +self.addEventListener('notificationclick', event => { + console.log('Service Worker: Notification clicked', event); + + event.notification.close(); + + if (event.action === 'close') { + return; + } + + const url = event.notification.data || '/'; + + event.waitUntil( + clients.matchAll({ type: 'window' }).then(clientList => { + // Check if window is already open + for (const client of clientList) { + if (client.url === url && 'focus' in client) { + return client.focus(); + } + } + + // Open new window + if (clients.openWindow) { + return clients.openWindow(url); + } + }) + ); +}); + +// Handle messages from main thread +self.addEventListener('message', event => { + console.log('Service Worker: Message received', event.data); + + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } + + if (event.data && event.data.type === 'CACHE_URLS') { + cacheUrls(event.data.urls); + } +}); + +async function cacheUrls(urls) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + await cache.addAll(urls); + console.log('URLs cached successfully:', urls); + } catch (error) { + console.error('Failed to cache URLs:', error); + } +} + +// Periodic background sync (if supported) +self.addEventListener('periodicsync', event => { + console.log('Service Worker: Periodic sync triggered', event.tag); + + if (event.tag === 'content-sync') { + event.waitUntil(syncContent()); + } +}); + +async function syncContent() { + try { + // Fetch fresh portfolio and services data + const portfolioResponse = await fetch('/api/portfolio?featured=true'); + const servicesResponse = await fetch('/api/services?featured=true'); + + if (portfolioResponse.ok && servicesResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put('/api/portfolio?featured=true', portfolioResponse.clone()); + cache.put('/api/services?featured=true', servicesResponse.clone()); + console.log('Content synced successfully'); + } + } catch (error) { + console.error('Content sync failed:', error); + } +} + +// Cache management utilities +async function cleanupCaches() { + const cacheNames = await caches.keys(); + const currentCaches = [STATIC_CACHE_NAME, DYNAMIC_CACHE_NAME]; + + return Promise.all( + cacheNames.map(cacheName => { + if (!currentCaches.includes(cacheName)) { + console.log('Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); +} + +// Limit cache size +async function limitCacheSize(cacheName, maxItems) { + const cache = await caches.open(cacheName); + const keys = await cache.keys(); + + if (keys.length > maxItems) { + const keysToDelete = keys.slice(0, keys.length - maxItems); + return Promise.all(keysToDelete.map(key => cache.delete(key))); + } +} + +// Performance monitoring +self.addEventListener('fetch', event => { + if (event.request.url.includes('/api/')) { + const start = performance.now(); + + event.respondWith( + fetch(event.request).then(response => { + const duration = performance.now() - start; + + // Log slow API requests + if (duration > 2000) { + console.warn('Slow API request:', event.request.url, duration + 'ms'); + } + + return response; + }) + ); + } +}); + +// Error tracking +self.addEventListener('error', event => { + console.error('Service Worker error:', event.error); + // Could send to analytics service +}); + +self.addEventListener('unhandledrejection', event => { + console.error('Service Worker unhandled rejection:', event.reason); + // Could send to analytics service +}); \ No newline at end of file diff --git a/.history/public/sw_20251020042624.js b/.history/public/sw_20251020042624.js new file mode 100644 index 0000000..9c6821c --- /dev/null +++ b/.history/public/sw_20251020042624.js @@ -0,0 +1,399 @@ +// Service Worker for SmartSolTech PWA +const CACHE_NAME = 'smartsoltech-v1.0.1'; +const STATIC_CACHE_NAME = 'smartsoltech-static-v1.0.1'; +const DYNAMIC_CACHE_NAME = 'smartsoltech-dynamic-v1.0.1'; + +// Files to cache immediately +const STATIC_FILES = [ + '/', + '/css/main.css', + '/css/fixes.css', + '/css/dark-theme.css', + '/js/main.js', + '/images/logo.png', + '/images/icon-192x192.png', + '/images/icon-144x144.png', + '/manifest.json', + 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', + 'https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.js' +]; + +// Routes to cache dynamically +const DYNAMIC_ROUTES = [ + '/about', + '/services', + '/portfolio', + '/calculator', + '/contact' +]; + +// API endpoints to cache +const API_CACHE_PATTERNS = [ + /^\/api\/portfolio/, + /^\/api\/services/, + /^\/api\/calculator\/services/ +]; + +// Install event - cache static files +self.addEventListener('install', event => { + console.log('Service Worker: Installing...'); + + event.waitUntil( + caches.open(STATIC_CACHE_NAME) + .then(cache => { + console.log('Service Worker: Caching static files'); + return cache.addAll(STATIC_FILES); + }) + .then(() => { + console.log('Service Worker: Static files cached'); + return self.skipWaiting(); + }) + .catch(error => { + console.error('Service Worker: Error caching static files', error); + }) + ); +}); + +// Activate event - clean up old caches +self.addEventListener('activate', event => { + console.log('Service Worker: Activating...'); + + event.waitUntil( + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== STATIC_CACHE_NAME && + cacheName !== DYNAMIC_CACHE_NAME) { + console.log('Service Worker: Deleting old cache', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + .then(() => { + console.log('Service Worker: Activated'); + return self.clients.claim(); + }) + ); +}); + +// Fetch event - serve cached files or fetch from network +self.addEventListener('fetch', event => { + const request = event.request; + const url = new URL(request.url); + + // Skip non-GET requests + if (request.method !== 'GET') { + return; + } + + // Skip Chrome extension requests + if (url.protocol === 'chrome-extension:') { + return; + } + + // Handle different types of requests + if (isStaticFile(request.url)) { + event.respondWith(cacheFirst(request)); + } else if (isAPIRequest(request.url)) { + event.respondWith(networkFirst(request)); + } else if (isDynamicRoute(request.url)) { + event.respondWith(staleWhileRevalidate(request)); + } else { + event.respondWith(networkFirst(request)); + } +}); + +// Cache strategies +async function cacheFirst(request) { + try { + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + const networkResponse = await fetch(request); + const cache = await caches.open(STATIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + return networkResponse; + } catch (error) { + console.error('Cache first strategy failed:', error); + return new Response('Offline', { status: 503 }); + } +} + +async function networkFirst(request) { + try { + const networkResponse = await fetch(request); + + // Cache successful responses + if (networkResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + } + + return networkResponse; + } catch (error) { + console.log('Network first: Falling back to cache for', request.url); + + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + // Return offline page for navigation requests + if (request.mode === 'navigate') { + return caches.match('/offline.html') || new Response('Offline', { + status: 503, + headers: { 'Content-Type': 'text/html' } + }); + } + + return new Response('Network Error', { status: 503 }); + } +} + +async function staleWhileRevalidate(request) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const cachedResponse = await cache.match(request); + + const fetchPromise = fetch(request).then(networkResponse => { + if (networkResponse.ok) { + cache.put(request, networkResponse.clone()); + } + return networkResponse; + }); + + return cachedResponse || fetchPromise; +} + +// Helper functions +function isStaticFile(url) { + return url.includes('/css/') || + url.includes('/js/') || + url.includes('/images/') || + url.includes('/fonts/') || + url.includes('googleapis.com') || + url.includes('cdnjs.cloudflare.com'); +} + +function isAPIRequest(url) { + return url.includes('/api/') || + API_CACHE_PATTERNS.some(pattern => pattern.test(url)); +} + +function isDynamicRoute(url) { + const pathname = new URL(url).pathname; + return DYNAMIC_ROUTES.includes(pathname) || + pathname.startsWith('/portfolio/') || + pathname.startsWith('/services/'); +} + +// Background sync for form submissions +self.addEventListener('sync', event => { + console.log('Service Worker: Background sync triggered', event.tag); + + if (event.tag === 'contact-form-sync') { + event.waitUntil(syncContactForms()); + } +}); + +async function syncContactForms() { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const requests = await cache.keys(); + + const contactRequests = requests.filter(request => + request.url.includes('/api/contact/submit') + ); + + for (const request of contactRequests) { + try { + await fetch(request); + await cache.delete(request); + console.log('Contact form synced successfully'); + } catch (error) { + console.error('Failed to sync contact form:', error); + } + } + } catch (error) { + console.error('Background sync failed:', error); + } +} + +// Push notification handling +self.addEventListener('push', event => { + console.log('Service Worker: Push received', event); + + let data = {}; + if (event.data) { + data = event.data.json(); + } + + const title = data.title || 'SmartSolTech'; + const options = { + body: data.body || 'You have a new notification', + icon: '/images/icon-192x192.png', + badge: '/images/icon-72x72.png', + tag: data.tag || 'default', + data: data.url || '/', + actions: [ + { + action: 'open', + title: '열기', + icon: '/images/icon-open.png' + }, + { + action: 'close', + title: '닫기', + icon: '/images/icon-close.png' + } + ], + requireInteraction: data.requireInteraction || false, + silent: data.silent || false, + vibrate: data.vibrate || [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification(title, options) + ); +}); + +// Notification click handling +self.addEventListener('notificationclick', event => { + console.log('Service Worker: Notification clicked', event); + + event.notification.close(); + + if (event.action === 'close') { + return; + } + + const url = event.notification.data || '/'; + + event.waitUntil( + clients.matchAll({ type: 'window' }).then(clientList => { + // Check if window is already open + for (const client of clientList) { + if (client.url === url && 'focus' in client) { + return client.focus(); + } + } + + // Open new window + if (clients.openWindow) { + return clients.openWindow(url); + } + }) + ); +}); + +// Handle messages from main thread +self.addEventListener('message', event => { + console.log('Service Worker: Message received', event.data); + + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } + + if (event.data && event.data.type === 'CACHE_URLS') { + cacheUrls(event.data.urls); + } +}); + +async function cacheUrls(urls) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + await cache.addAll(urls); + console.log('URLs cached successfully:', urls); + } catch (error) { + console.error('Failed to cache URLs:', error); + } +} + +// Periodic background sync (if supported) +self.addEventListener('periodicsync', event => { + console.log('Service Worker: Periodic sync triggered', event.tag); + + if (event.tag === 'content-sync') { + event.waitUntil(syncContent()); + } +}); + +async function syncContent() { + try { + // Fetch fresh portfolio and services data + const portfolioResponse = await fetch('/api/portfolio?featured=true'); + const servicesResponse = await fetch('/api/services?featured=true'); + + if (portfolioResponse.ok && servicesResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put('/api/portfolio?featured=true', portfolioResponse.clone()); + cache.put('/api/services?featured=true', servicesResponse.clone()); + console.log('Content synced successfully'); + } + } catch (error) { + console.error('Content sync failed:', error); + } +} + +// Cache management utilities +async function cleanupCaches() { + const cacheNames = await caches.keys(); + const currentCaches = [STATIC_CACHE_NAME, DYNAMIC_CACHE_NAME]; + + return Promise.all( + cacheNames.map(cacheName => { + if (!currentCaches.includes(cacheName)) { + console.log('Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); +} + +// Limit cache size +async function limitCacheSize(cacheName, maxItems) { + const cache = await caches.open(cacheName); + const keys = await cache.keys(); + + if (keys.length > maxItems) { + const keysToDelete = keys.slice(0, keys.length - maxItems); + return Promise.all(keysToDelete.map(key => cache.delete(key))); + } +} + +// Performance monitoring +self.addEventListener('fetch', event => { + if (event.request.url.includes('/api/')) { + const start = performance.now(); + + event.respondWith( + fetch(event.request).then(response => { + const duration = performance.now() - start; + + // Log slow API requests + if (duration > 2000) { + console.warn('Slow API request:', event.request.url, duration + 'ms'); + } + + return response; + }) + ); + } +}); + +// Error tracking +self.addEventListener('error', event => { + console.error('Service Worker error:', event.error); + // Could send to analytics service +}); + +self.addEventListener('unhandledrejection', event => { + console.error('Service Worker unhandled rejection:', event.reason); + // Could send to analytics service +}); \ No newline at end of file diff --git a/.history/public/sw_20251020042633.js b/.history/public/sw_20251020042633.js new file mode 100644 index 0000000..9c6821c --- /dev/null +++ b/.history/public/sw_20251020042633.js @@ -0,0 +1,399 @@ +// Service Worker for SmartSolTech PWA +const CACHE_NAME = 'smartsoltech-v1.0.1'; +const STATIC_CACHE_NAME = 'smartsoltech-static-v1.0.1'; +const DYNAMIC_CACHE_NAME = 'smartsoltech-dynamic-v1.0.1'; + +// Files to cache immediately +const STATIC_FILES = [ + '/', + '/css/main.css', + '/css/fixes.css', + '/css/dark-theme.css', + '/js/main.js', + '/images/logo.png', + '/images/icon-192x192.png', + '/images/icon-144x144.png', + '/manifest.json', + 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', + 'https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.js' +]; + +// Routes to cache dynamically +const DYNAMIC_ROUTES = [ + '/about', + '/services', + '/portfolio', + '/calculator', + '/contact' +]; + +// API endpoints to cache +const API_CACHE_PATTERNS = [ + /^\/api\/portfolio/, + /^\/api\/services/, + /^\/api\/calculator\/services/ +]; + +// Install event - cache static files +self.addEventListener('install', event => { + console.log('Service Worker: Installing...'); + + event.waitUntil( + caches.open(STATIC_CACHE_NAME) + .then(cache => { + console.log('Service Worker: Caching static files'); + return cache.addAll(STATIC_FILES); + }) + .then(() => { + console.log('Service Worker: Static files cached'); + return self.skipWaiting(); + }) + .catch(error => { + console.error('Service Worker: Error caching static files', error); + }) + ); +}); + +// Activate event - clean up old caches +self.addEventListener('activate', event => { + console.log('Service Worker: Activating...'); + + event.waitUntil( + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== STATIC_CACHE_NAME && + cacheName !== DYNAMIC_CACHE_NAME) { + console.log('Service Worker: Deleting old cache', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + .then(() => { + console.log('Service Worker: Activated'); + return self.clients.claim(); + }) + ); +}); + +// Fetch event - serve cached files or fetch from network +self.addEventListener('fetch', event => { + const request = event.request; + const url = new URL(request.url); + + // Skip non-GET requests + if (request.method !== 'GET') { + return; + } + + // Skip Chrome extension requests + if (url.protocol === 'chrome-extension:') { + return; + } + + // Handle different types of requests + if (isStaticFile(request.url)) { + event.respondWith(cacheFirst(request)); + } else if (isAPIRequest(request.url)) { + event.respondWith(networkFirst(request)); + } else if (isDynamicRoute(request.url)) { + event.respondWith(staleWhileRevalidate(request)); + } else { + event.respondWith(networkFirst(request)); + } +}); + +// Cache strategies +async function cacheFirst(request) { + try { + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + const networkResponse = await fetch(request); + const cache = await caches.open(STATIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + return networkResponse; + } catch (error) { + console.error('Cache first strategy failed:', error); + return new Response('Offline', { status: 503 }); + } +} + +async function networkFirst(request) { + try { + const networkResponse = await fetch(request); + + // Cache successful responses + if (networkResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + } + + return networkResponse; + } catch (error) { + console.log('Network first: Falling back to cache for', request.url); + + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + // Return offline page for navigation requests + if (request.mode === 'navigate') { + return caches.match('/offline.html') || new Response('Offline', { + status: 503, + headers: { 'Content-Type': 'text/html' } + }); + } + + return new Response('Network Error', { status: 503 }); + } +} + +async function staleWhileRevalidate(request) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const cachedResponse = await cache.match(request); + + const fetchPromise = fetch(request).then(networkResponse => { + if (networkResponse.ok) { + cache.put(request, networkResponse.clone()); + } + return networkResponse; + }); + + return cachedResponse || fetchPromise; +} + +// Helper functions +function isStaticFile(url) { + return url.includes('/css/') || + url.includes('/js/') || + url.includes('/images/') || + url.includes('/fonts/') || + url.includes('googleapis.com') || + url.includes('cdnjs.cloudflare.com'); +} + +function isAPIRequest(url) { + return url.includes('/api/') || + API_CACHE_PATTERNS.some(pattern => pattern.test(url)); +} + +function isDynamicRoute(url) { + const pathname = new URL(url).pathname; + return DYNAMIC_ROUTES.includes(pathname) || + pathname.startsWith('/portfolio/') || + pathname.startsWith('/services/'); +} + +// Background sync for form submissions +self.addEventListener('sync', event => { + console.log('Service Worker: Background sync triggered', event.tag); + + if (event.tag === 'contact-form-sync') { + event.waitUntil(syncContactForms()); + } +}); + +async function syncContactForms() { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const requests = await cache.keys(); + + const contactRequests = requests.filter(request => + request.url.includes('/api/contact/submit') + ); + + for (const request of contactRequests) { + try { + await fetch(request); + await cache.delete(request); + console.log('Contact form synced successfully'); + } catch (error) { + console.error('Failed to sync contact form:', error); + } + } + } catch (error) { + console.error('Background sync failed:', error); + } +} + +// Push notification handling +self.addEventListener('push', event => { + console.log('Service Worker: Push received', event); + + let data = {}; + if (event.data) { + data = event.data.json(); + } + + const title = data.title || 'SmartSolTech'; + const options = { + body: data.body || 'You have a new notification', + icon: '/images/icon-192x192.png', + badge: '/images/icon-72x72.png', + tag: data.tag || 'default', + data: data.url || '/', + actions: [ + { + action: 'open', + title: '열기', + icon: '/images/icon-open.png' + }, + { + action: 'close', + title: '닫기', + icon: '/images/icon-close.png' + } + ], + requireInteraction: data.requireInteraction || false, + silent: data.silent || false, + vibrate: data.vibrate || [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification(title, options) + ); +}); + +// Notification click handling +self.addEventListener('notificationclick', event => { + console.log('Service Worker: Notification clicked', event); + + event.notification.close(); + + if (event.action === 'close') { + return; + } + + const url = event.notification.data || '/'; + + event.waitUntil( + clients.matchAll({ type: 'window' }).then(clientList => { + // Check if window is already open + for (const client of clientList) { + if (client.url === url && 'focus' in client) { + return client.focus(); + } + } + + // Open new window + if (clients.openWindow) { + return clients.openWindow(url); + } + }) + ); +}); + +// Handle messages from main thread +self.addEventListener('message', event => { + console.log('Service Worker: Message received', event.data); + + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } + + if (event.data && event.data.type === 'CACHE_URLS') { + cacheUrls(event.data.urls); + } +}); + +async function cacheUrls(urls) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + await cache.addAll(urls); + console.log('URLs cached successfully:', urls); + } catch (error) { + console.error('Failed to cache URLs:', error); + } +} + +// Periodic background sync (if supported) +self.addEventListener('periodicsync', event => { + console.log('Service Worker: Periodic sync triggered', event.tag); + + if (event.tag === 'content-sync') { + event.waitUntil(syncContent()); + } +}); + +async function syncContent() { + try { + // Fetch fresh portfolio and services data + const portfolioResponse = await fetch('/api/portfolio?featured=true'); + const servicesResponse = await fetch('/api/services?featured=true'); + + if (portfolioResponse.ok && servicesResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put('/api/portfolio?featured=true', portfolioResponse.clone()); + cache.put('/api/services?featured=true', servicesResponse.clone()); + console.log('Content synced successfully'); + } + } catch (error) { + console.error('Content sync failed:', error); + } +} + +// Cache management utilities +async function cleanupCaches() { + const cacheNames = await caches.keys(); + const currentCaches = [STATIC_CACHE_NAME, DYNAMIC_CACHE_NAME]; + + return Promise.all( + cacheNames.map(cacheName => { + if (!currentCaches.includes(cacheName)) { + console.log('Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); +} + +// Limit cache size +async function limitCacheSize(cacheName, maxItems) { + const cache = await caches.open(cacheName); + const keys = await cache.keys(); + + if (keys.length > maxItems) { + const keysToDelete = keys.slice(0, keys.length - maxItems); + return Promise.all(keysToDelete.map(key => cache.delete(key))); + } +} + +// Performance monitoring +self.addEventListener('fetch', event => { + if (event.request.url.includes('/api/')) { + const start = performance.now(); + + event.respondWith( + fetch(event.request).then(response => { + const duration = performance.now() - start; + + // Log slow API requests + if (duration > 2000) { + console.warn('Slow API request:', event.request.url, duration + 'ms'); + } + + return response; + }) + ); + } +}); + +// Error tracking +self.addEventListener('error', event => { + console.error('Service Worker error:', event.error); + // Could send to analytics service +}); + +self.addEventListener('unhandledrejection', event => { + console.error('Service Worker unhandled rejection:', event.reason); + // Could send to analytics service +}); \ No newline at end of file diff --git a/.history/public/sw_20251021172445.js b/.history/public/sw_20251021172445.js new file mode 100644 index 0000000..94421c1 --- /dev/null +++ b/.history/public/sw_20251021172445.js @@ -0,0 +1,407 @@ +// Service Worker for SmartSolTech PWA +const CACHE_NAME = 'smartsoltech-v1.0.1'; +const STATIC_CACHE_NAME = 'smartsoltech-static-v1.0.1'; +const DYNAMIC_CACHE_NAME = 'smartsoltech-dynamic-v1.0.1'; + +// Files to cache immediately +const STATIC_FILES = [ + '/', + '/css/main.css', + '/css/fixes.css', + '/css/dark-theme.css', + '/js/main.js', + '/images/logo.png', + '/images/icon-192x192.png', + '/images/icon-144x144.png', + '/manifest.json', + 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', + 'https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.js' +]; + +// Routes to cache dynamically +const DYNAMIC_ROUTES = [ + '/about', + '/services', + '/portfolio', + '/calculator', + '/contact' +]; + +// API endpoints to cache +const API_CACHE_PATTERNS = [ + /^\/api\/portfolio/, + /^\/api\/services/, + /^\/api\/calculator\/services/ +]; + +// Install event - cache static files +self.addEventListener('install', event => { + console.log('Service Worker: Installing...'); + + event.waitUntil( + caches.open(STATIC_CACHE_NAME) + .then(cache => { + console.log('Service Worker: Caching static files'); + return cache.addAll(STATIC_FILES); + }) + .then(() => { + console.log('Service Worker: Static files cached'); + return self.skipWaiting(); + }) + .catch(error => { + console.error('Service Worker: Error caching static files', error); + }) + ); +}); + +// Activate event - clean up old caches +self.addEventListener('activate', event => { + console.log('Service Worker: Activating...'); + + event.waitUntil( + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== STATIC_CACHE_NAME && + cacheName !== DYNAMIC_CACHE_NAME) { + console.log('Service Worker: Deleting old cache', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + .then(() => { + console.log('Service Worker: Activated'); + return self.clients.claim(); + }) + ); +}); + +// Fetch event - serve cached files or fetch from network +self.addEventListener('fetch', event => { + const request = event.request; + const url = new URL(request.url); + + // Skip non-GET requests + if (request.method !== 'GET') { + return; + } + + // Skip Chrome extension requests + if (url.protocol === 'chrome-extension:') { + return; + } + + // Handle different types of requests + if (isStaticFile(request.url)) { + event.respondWith(cacheFirst(request)); + } else if (isAPIRequest(request.url)) { + event.respondWith(networkFirst(request)); + } else if (isDynamicRoute(request.url)) { + event.respondWith(staleWhileRevalidate(request)); + } else { + event.respondWith(networkFirst(request)); + } +}); + +// Cache strategies +async function cacheFirst(request) { + try { + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + const networkResponse = await fetch(request); + const cache = await caches.open(STATIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + return networkResponse; + } catch (error) { + console.error('Cache first strategy failed:', error); + return new Response('Offline', { status: 503 }); + } +} + +async function networkFirst(request) { + try { + const networkResponse = await fetch(request); + + // Cache successful responses + if (networkResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + } + + return networkResponse; + } catch (error) { + console.log('Network first: Falling back to cache for', request.url); + + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + // Return offline page for navigation requests + if (request.mode === 'navigate') { + return caches.match('/offline.html') || new Response('Offline', { + status: 503, + headers: { 'Content-Type': 'text/html' } + }); + } + + return new Response('Network Error', { status: 503 }); + } +} + +async function staleWhileRevalidate(request) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const cachedResponse = await cache.match(request); + + const fetchPromise = fetch(request).then(networkResponse => { + if (networkResponse && networkResponse.ok) { + cache.put(request, networkResponse.clone()); + } + return networkResponse; + }).catch(error => { + console.log('staleWhileRevalidate fetch failed:', error); + return null; + }); + + return cachedResponse || fetchPromise || new Response('Not available', { status: 503 }); + } catch (error) { + console.error('staleWhileRevalidate error:', error); + return new Response('Service unavailable', { status: 503 }); + } +} + +// Helper functions +function isStaticFile(url) { + return url.includes('/css/') || + url.includes('/js/') || + url.includes('/images/') || + url.includes('/fonts/') || + url.includes('googleapis.com') || + url.includes('cdnjs.cloudflare.com'); +} + +function isAPIRequest(url) { + return url.includes('/api/') || + API_CACHE_PATTERNS.some(pattern => pattern.test(url)); +} + +function isDynamicRoute(url) { + const pathname = new URL(url).pathname; + return DYNAMIC_ROUTES.includes(pathname) || + pathname.startsWith('/portfolio/') || + pathname.startsWith('/services/'); +} + +// Background sync for form submissions +self.addEventListener('sync', event => { + console.log('Service Worker: Background sync triggered', event.tag); + + if (event.tag === 'contact-form-sync') { + event.waitUntil(syncContactForms()); + } +}); + +async function syncContactForms() { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const requests = await cache.keys(); + + const contactRequests = requests.filter(request => + request.url.includes('/api/contact/submit') + ); + + for (const request of contactRequests) { + try { + await fetch(request); + await cache.delete(request); + console.log('Contact form synced successfully'); + } catch (error) { + console.error('Failed to sync contact form:', error); + } + } + } catch (error) { + console.error('Background sync failed:', error); + } +} + +// Push notification handling +self.addEventListener('push', event => { + console.log('Service Worker: Push received', event); + + let data = {}; + if (event.data) { + data = event.data.json(); + } + + const title = data.title || 'SmartSolTech'; + const options = { + body: data.body || 'You have a new notification', + icon: '/images/icon-192x192.png', + badge: '/images/icon-72x72.png', + tag: data.tag || 'default', + data: data.url || '/', + actions: [ + { + action: 'open', + title: '열기', + icon: '/images/icon-open.png' + }, + { + action: 'close', + title: '닫기', + icon: '/images/icon-close.png' + } + ], + requireInteraction: data.requireInteraction || false, + silent: data.silent || false, + vibrate: data.vibrate || [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification(title, options) + ); +}); + +// Notification click handling +self.addEventListener('notificationclick', event => { + console.log('Service Worker: Notification clicked', event); + + event.notification.close(); + + if (event.action === 'close') { + return; + } + + const url = event.notification.data || '/'; + + event.waitUntil( + clients.matchAll({ type: 'window' }).then(clientList => { + // Check if window is already open + for (const client of clientList) { + if (client.url === url && 'focus' in client) { + return client.focus(); + } + } + + // Open new window + if (clients.openWindow) { + return clients.openWindow(url); + } + }) + ); +}); + +// Handle messages from main thread +self.addEventListener('message', event => { + console.log('Service Worker: Message received', event.data); + + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } + + if (event.data && event.data.type === 'CACHE_URLS') { + cacheUrls(event.data.urls); + } +}); + +async function cacheUrls(urls) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + await cache.addAll(urls); + console.log('URLs cached successfully:', urls); + } catch (error) { + console.error('Failed to cache URLs:', error); + } +} + +// Periodic background sync (if supported) +self.addEventListener('periodicsync', event => { + console.log('Service Worker: Periodic sync triggered', event.tag); + + if (event.tag === 'content-sync') { + event.waitUntil(syncContent()); + } +}); + +async function syncContent() { + try { + // Fetch fresh portfolio and services data + const portfolioResponse = await fetch('/api/portfolio?featured=true'); + const servicesResponse = await fetch('/api/services?featured=true'); + + if (portfolioResponse.ok && servicesResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put('/api/portfolio?featured=true', portfolioResponse.clone()); + cache.put('/api/services?featured=true', servicesResponse.clone()); + console.log('Content synced successfully'); + } + } catch (error) { + console.error('Content sync failed:', error); + } +} + +// Cache management utilities +async function cleanupCaches() { + const cacheNames = await caches.keys(); + const currentCaches = [STATIC_CACHE_NAME, DYNAMIC_CACHE_NAME]; + + return Promise.all( + cacheNames.map(cacheName => { + if (!currentCaches.includes(cacheName)) { + console.log('Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); +} + +// Limit cache size +async function limitCacheSize(cacheName, maxItems) { + const cache = await caches.open(cacheName); + const keys = await cache.keys(); + + if (keys.length > maxItems) { + const keysToDelete = keys.slice(0, keys.length - maxItems); + return Promise.all(keysToDelete.map(key => cache.delete(key))); + } +} + +// Performance monitoring +self.addEventListener('fetch', event => { + if (event.request.url.includes('/api/')) { + const start = performance.now(); + + event.respondWith( + fetch(event.request).then(response => { + const duration = performance.now() - start; + + // Log slow API requests + if (duration > 2000) { + console.warn('Slow API request:', event.request.url, duration + 'ms'); + } + + return response; + }) + ); + } +}); + +// Error tracking +self.addEventListener('error', event => { + console.error('Service Worker error:', event.error); + // Could send to analytics service +}); + +self.addEventListener('unhandledrejection', event => { + console.error('Service Worker unhandled rejection:', event.reason); + // Could send to analytics service +}); \ No newline at end of file diff --git a/.history/public/sw_20251021172602.js b/.history/public/sw_20251021172602.js new file mode 100644 index 0000000..94421c1 --- /dev/null +++ b/.history/public/sw_20251021172602.js @@ -0,0 +1,407 @@ +// Service Worker for SmartSolTech PWA +const CACHE_NAME = 'smartsoltech-v1.0.1'; +const STATIC_CACHE_NAME = 'smartsoltech-static-v1.0.1'; +const DYNAMIC_CACHE_NAME = 'smartsoltech-dynamic-v1.0.1'; + +// Files to cache immediately +const STATIC_FILES = [ + '/', + '/css/main.css', + '/css/fixes.css', + '/css/dark-theme.css', + '/js/main.js', + '/images/logo.png', + '/images/icon-192x192.png', + '/images/icon-144x144.png', + '/manifest.json', + 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', + 'https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.css', + 'https://unpkg.com/aos@2.3.1/dist/aos.js' +]; + +// Routes to cache dynamically +const DYNAMIC_ROUTES = [ + '/about', + '/services', + '/portfolio', + '/calculator', + '/contact' +]; + +// API endpoints to cache +const API_CACHE_PATTERNS = [ + /^\/api\/portfolio/, + /^\/api\/services/, + /^\/api\/calculator\/services/ +]; + +// Install event - cache static files +self.addEventListener('install', event => { + console.log('Service Worker: Installing...'); + + event.waitUntil( + caches.open(STATIC_CACHE_NAME) + .then(cache => { + console.log('Service Worker: Caching static files'); + return cache.addAll(STATIC_FILES); + }) + .then(() => { + console.log('Service Worker: Static files cached'); + return self.skipWaiting(); + }) + .catch(error => { + console.error('Service Worker: Error caching static files', error); + }) + ); +}); + +// Activate event - clean up old caches +self.addEventListener('activate', event => { + console.log('Service Worker: Activating...'); + + event.waitUntil( + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== STATIC_CACHE_NAME && + cacheName !== DYNAMIC_CACHE_NAME) { + console.log('Service Worker: Deleting old cache', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + .then(() => { + console.log('Service Worker: Activated'); + return self.clients.claim(); + }) + ); +}); + +// Fetch event - serve cached files or fetch from network +self.addEventListener('fetch', event => { + const request = event.request; + const url = new URL(request.url); + + // Skip non-GET requests + if (request.method !== 'GET') { + return; + } + + // Skip Chrome extension requests + if (url.protocol === 'chrome-extension:') { + return; + } + + // Handle different types of requests + if (isStaticFile(request.url)) { + event.respondWith(cacheFirst(request)); + } else if (isAPIRequest(request.url)) { + event.respondWith(networkFirst(request)); + } else if (isDynamicRoute(request.url)) { + event.respondWith(staleWhileRevalidate(request)); + } else { + event.respondWith(networkFirst(request)); + } +}); + +// Cache strategies +async function cacheFirst(request) { + try { + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + const networkResponse = await fetch(request); + const cache = await caches.open(STATIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + return networkResponse; + } catch (error) { + console.error('Cache first strategy failed:', error); + return new Response('Offline', { status: 503 }); + } +} + +async function networkFirst(request) { + try { + const networkResponse = await fetch(request); + + // Cache successful responses + if (networkResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put(request, networkResponse.clone()); + } + + return networkResponse; + } catch (error) { + console.log('Network first: Falling back to cache for', request.url); + + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + + // Return offline page for navigation requests + if (request.mode === 'navigate') { + return caches.match('/offline.html') || new Response('Offline', { + status: 503, + headers: { 'Content-Type': 'text/html' } + }); + } + + return new Response('Network Error', { status: 503 }); + } +} + +async function staleWhileRevalidate(request) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const cachedResponse = await cache.match(request); + + const fetchPromise = fetch(request).then(networkResponse => { + if (networkResponse && networkResponse.ok) { + cache.put(request, networkResponse.clone()); + } + return networkResponse; + }).catch(error => { + console.log('staleWhileRevalidate fetch failed:', error); + return null; + }); + + return cachedResponse || fetchPromise || new Response('Not available', { status: 503 }); + } catch (error) { + console.error('staleWhileRevalidate error:', error); + return new Response('Service unavailable', { status: 503 }); + } +} + +// Helper functions +function isStaticFile(url) { + return url.includes('/css/') || + url.includes('/js/') || + url.includes('/images/') || + url.includes('/fonts/') || + url.includes('googleapis.com') || + url.includes('cdnjs.cloudflare.com'); +} + +function isAPIRequest(url) { + return url.includes('/api/') || + API_CACHE_PATTERNS.some(pattern => pattern.test(url)); +} + +function isDynamicRoute(url) { + const pathname = new URL(url).pathname; + return DYNAMIC_ROUTES.includes(pathname) || + pathname.startsWith('/portfolio/') || + pathname.startsWith('/services/'); +} + +// Background sync for form submissions +self.addEventListener('sync', event => { + console.log('Service Worker: Background sync triggered', event.tag); + + if (event.tag === 'contact-form-sync') { + event.waitUntil(syncContactForms()); + } +}); + +async function syncContactForms() { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + const requests = await cache.keys(); + + const contactRequests = requests.filter(request => + request.url.includes('/api/contact/submit') + ); + + for (const request of contactRequests) { + try { + await fetch(request); + await cache.delete(request); + console.log('Contact form synced successfully'); + } catch (error) { + console.error('Failed to sync contact form:', error); + } + } + } catch (error) { + console.error('Background sync failed:', error); + } +} + +// Push notification handling +self.addEventListener('push', event => { + console.log('Service Worker: Push received', event); + + let data = {}; + if (event.data) { + data = event.data.json(); + } + + const title = data.title || 'SmartSolTech'; + const options = { + body: data.body || 'You have a new notification', + icon: '/images/icon-192x192.png', + badge: '/images/icon-72x72.png', + tag: data.tag || 'default', + data: data.url || '/', + actions: [ + { + action: 'open', + title: '열기', + icon: '/images/icon-open.png' + }, + { + action: 'close', + title: '닫기', + icon: '/images/icon-close.png' + } + ], + requireInteraction: data.requireInteraction || false, + silent: data.silent || false, + vibrate: data.vibrate || [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification(title, options) + ); +}); + +// Notification click handling +self.addEventListener('notificationclick', event => { + console.log('Service Worker: Notification clicked', event); + + event.notification.close(); + + if (event.action === 'close') { + return; + } + + const url = event.notification.data || '/'; + + event.waitUntil( + clients.matchAll({ type: 'window' }).then(clientList => { + // Check if window is already open + for (const client of clientList) { + if (client.url === url && 'focus' in client) { + return client.focus(); + } + } + + // Open new window + if (clients.openWindow) { + return clients.openWindow(url); + } + }) + ); +}); + +// Handle messages from main thread +self.addEventListener('message', event => { + console.log('Service Worker: Message received', event.data); + + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } + + if (event.data && event.data.type === 'CACHE_URLS') { + cacheUrls(event.data.urls); + } +}); + +async function cacheUrls(urls) { + try { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + await cache.addAll(urls); + console.log('URLs cached successfully:', urls); + } catch (error) { + console.error('Failed to cache URLs:', error); + } +} + +// Periodic background sync (if supported) +self.addEventListener('periodicsync', event => { + console.log('Service Worker: Periodic sync triggered', event.tag); + + if (event.tag === 'content-sync') { + event.waitUntil(syncContent()); + } +}); + +async function syncContent() { + try { + // Fetch fresh portfolio and services data + const portfolioResponse = await fetch('/api/portfolio?featured=true'); + const servicesResponse = await fetch('/api/services?featured=true'); + + if (portfolioResponse.ok && servicesResponse.ok) { + const cache = await caches.open(DYNAMIC_CACHE_NAME); + cache.put('/api/portfolio?featured=true', portfolioResponse.clone()); + cache.put('/api/services?featured=true', servicesResponse.clone()); + console.log('Content synced successfully'); + } + } catch (error) { + console.error('Content sync failed:', error); + } +} + +// Cache management utilities +async function cleanupCaches() { + const cacheNames = await caches.keys(); + const currentCaches = [STATIC_CACHE_NAME, DYNAMIC_CACHE_NAME]; + + return Promise.all( + cacheNames.map(cacheName => { + if (!currentCaches.includes(cacheName)) { + console.log('Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); +} + +// Limit cache size +async function limitCacheSize(cacheName, maxItems) { + const cache = await caches.open(cacheName); + const keys = await cache.keys(); + + if (keys.length > maxItems) { + const keysToDelete = keys.slice(0, keys.length - maxItems); + return Promise.all(keysToDelete.map(key => cache.delete(key))); + } +} + +// Performance monitoring +self.addEventListener('fetch', event => { + if (event.request.url.includes('/api/')) { + const start = performance.now(); + + event.respondWith( + fetch(event.request).then(response => { + const duration = performance.now() - start; + + // Log slow API requests + if (duration > 2000) { + console.warn('Slow API request:', event.request.url, duration + 'ms'); + } + + return response; + }) + ); + } +}); + +// Error tracking +self.addEventListener('error', event => { + console.error('Service Worker error:', event.error); + // Could send to analytics service +}); + +self.addEventListener('unhandledrejection', event => { + console.error('Service Worker unhandled rejection:', event.reason); + // Could send to analytics service +}); \ No newline at end of file diff --git a/.history/routes/admin_20251019202120.js b/.history/routes/admin_20251019202120.js new file mode 100644 index 0000000..adec8e8 --- /dev/null +++ b/.history/routes/admin_20251019202120.js @@ -0,0 +1,383 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ email, isActive: true }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.countDocuments({ isPublished: true }), + Service.countDocuments({ isActive: true }), + Contact.countDocuments(), + Contact.find().sort({ createdAt: -1 }).limit(5), + Portfolio.find({ isPublished: true }).sort({ createdAt: -1 }).limit(5) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.countDocuments({ isRead: false }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Portfolio.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019202126.js b/.history/routes/admin_20251019202126.js new file mode 100644 index 0000000..273444c --- /dev/null +++ b/.history/routes/admin_20251019202126.js @@ -0,0 +1,388 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.countDocuments({ isPublished: true }), + Service.countDocuments({ isActive: true }), + Contact.countDocuments(), + Contact.find().sort({ createdAt: -1 }).limit(5), + Portfolio.find({ isPublished: true }).sort({ createdAt: -1 }).limit(5) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.countDocuments({ isRead: false }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Portfolio.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019202132.js b/.history/routes/admin_20251019202132.js new file mode 100644 index 0000000..399d74a --- /dev/null +++ b/.history/routes/admin_20251019202132.js @@ -0,0 +1,388 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.countDocuments({ isPublished: true }), + Service.countDocuments({ isActive: true }), + Contact.countDocuments(), + Contact.find().sort({ createdAt: -1 }).limit(5), + Portfolio.find({ isPublished: true }).sort({ createdAt: -1 }).limit(5) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.countDocuments({ isRead: false }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Portfolio.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019202141.js b/.history/routes/admin_20251019202141.js new file mode 100644 index 0000000..06c7c64 --- /dev/null +++ b/.history/routes/admin_20251019202141.js @@ -0,0 +1,395 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.countDocuments({ isRead: false }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Portfolio.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019202147.js b/.history/routes/admin_20251019202147.js new file mode 100644 index 0000000..65fa613 --- /dev/null +++ b/.history/routes/admin_20251019202147.js @@ -0,0 +1,395 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Portfolio.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019202631.js b/.history/routes/admin_20251019202631.js new file mode 100644 index 0000000..65fa613 --- /dev/null +++ b/.history/routes/admin_20251019202631.js @@ -0,0 +1,395 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Portfolio.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204203.js b/.history/routes/admin_20251019204203.js new file mode 100644 index 0000000..cff7985 --- /dev/null +++ b/.history/routes/admin_20251019204203.js @@ -0,0 +1,396 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findById(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204212.js b/.history/routes/admin_20251019204212.js new file mode 100644 index 0000000..b15353e --- /dev/null +++ b/.history/routes/admin_20251019204212.js @@ -0,0 +1,396 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.find() + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Service.countDocuments() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204224.js b/.history/routes/admin_20251019204224.js new file mode 100644 index 0000000..e6abba0 --- /dev/null +++ b/.history/routes/admin_20251019204224.js @@ -0,0 +1,397 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findById(req.params.id) + .populate('portfolio', 'title'); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204235.js b/.history/routes/admin_20251019204235.js new file mode 100644 index 0000000..1682ba0 --- /dev/null +++ b/.history/routes/admin_20251019204235.js @@ -0,0 +1,396 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.find({ isPublished: true }) + .select('title category'); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204245.js b/.history/routes/admin_20251019204245.js new file mode 100644 index 0000000..29bd33c --- /dev/null +++ b/.history/routes/admin_20251019204245.js @@ -0,0 +1,398 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let query = {}; + if (status && status !== 'all') { + query.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit), + Contact.countDocuments(query) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204257.js b/.history/routes/admin_20251019204257.js new file mode 100644 index 0000000..1c9c434 --- /dev/null +++ b/.history/routes/admin_20251019204257.js @@ -0,0 +1,400 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findById(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204307.js b/.history/routes/admin_20251019204307.js new file mode 100644 index 0000000..3746273 --- /dev/null +++ b/.history/routes/admin_20251019204307.js @@ -0,0 +1,400 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || new SiteSettings(); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204323.js b/.history/routes/admin_20251019204323.js new file mode 100644 index 0000000..d923515 --- /dev/null +++ b/.history/routes/admin_20251019204323.js @@ -0,0 +1,400 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251019204805.js b/.history/routes/admin_20251019204805.js new file mode 100644 index 0000000..d923515 --- /dev/null +++ b/.history/routes/admin_20251019204805.js @@ -0,0 +1,400 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020044258.js b/.history/routes/admin_20251020044258.js new file mode 100644 index 0000000..8076f4d --- /dev/null +++ b/.history/routes/admin_20251020044258.js @@ -0,0 +1,399 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'Invalid email or password' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020044304.js b/.history/routes/admin_20251020044304.js new file mode 100644 index 0000000..5d00fdd --- /dev/null +++ b/.history/routes/admin_20251020044304.js @@ -0,0 +1,398 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login - SmartSolTech', + layout: 'admin/layout', + error: 'An error occurred. Please try again.' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020044311.js b/.history/routes/admin_20251020044311.js new file mode 100644 index 0000000..a901d2e --- /dev/null +++ b/.history/routes/admin_20251020044311.js @@ -0,0 +1,397 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020044317.js b/.history/routes/admin_20251020044317.js new file mode 100644 index 0000000..ab8f4f0 --- /dev/null +++ b/.history/routes/admin_20251020044317.js @@ -0,0 +1,402 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolio: portfolioCount, + services: servicesCount, + contacts: contactsCount, + unreadContacts: await Contact.count({ where: { isRead: false } }) + }; + + res.render('admin/dashboard', { + title: 'Dashboard - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020044325.js b/.history/routes/admin_20251020044325.js new file mode 100644 index 0000000..0006b12 --- /dev/null +++ b/.history/routes/admin_20251020044325.js @@ -0,0 +1,402 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020044351.js b/.history/routes/admin_20251020044351.js new file mode 100644 index 0000000..0006b12 --- /dev/null +++ b/.history/routes/admin_20251020044351.js @@ -0,0 +1,402 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020225524.js b/.history/routes/admin_20251020225524.js new file mode 100644 index 0000000..0c488a9 --- /dev/null +++ b/.history/routes/admin_20251020225524.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251020225526.js b/.history/routes/admin_20251020225526.js new file mode 100644 index 0000000..0c488a9 --- /dev/null +++ b/.history/routes/admin_20251020225526.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: req.t('admin.login'), + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251021214310.js b/.history/routes/admin_20251021214310.js new file mode 100644 index 0000000..f2e1b9f --- /dev/null +++ b/.history/routes/admin_20251021214310.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.invalid_credentials') + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251021214318.js b/.history/routes/admin_20251021214318.js new file mode 100644 index 0000000..066db72 --- /dev/null +++ b/.history/routes/admin_20251021214318.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: req.t('admin.login'), + error: req.t('errors.server_error') + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251021214326.js b/.history/routes/admin_20251021214326.js new file mode 100644 index 0000000..c9ab8dc --- /dev/null +++ b/.history/routes/admin_20251021214326.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: req.t('admin.dashboard'), + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251021214335.js b/.history/routes/admin_20251021214335.js new file mode 100644 index 0000000..219e18e --- /dev/null +++ b/.history/routes/admin_20251021214335.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251021214352.js b/.history/routes/admin_20251021214352.js new file mode 100644 index 0000000..219e18e --- /dev/null +++ b/.history/routes/admin_20251021214352.js @@ -0,0 +1,422 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022052409.js b/.history/routes/admin_20251022052409.js new file mode 100644 index 0000000..ea7dae9 --- /dev/null +++ b/.history/routes/admin_20251022052409.js @@ -0,0 +1,501 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, (req, res) => { + const telegramService = require('../services/telegram'); + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled + }); +}); + +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + await telegramService.sendMessage(testMessage); + + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot + }); + } else { + res.status(400).json({ + success: false, + message: result.message || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +router.post('/telegram/send', requireAuth, async (req, res) => { + try { + const { message } = req.body; + + if (!message || message.trim().length === 0) { + return res.status(400).json({ + success: false, + message: 'Message is required' + }); + } + + const telegramService = require('../services/telegram'); + const result = await telegramService.sendMessage(message); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to send message' + }); + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022052452.js b/.history/routes/admin_20251022052452.js new file mode 100644 index 0000000..ea7dae9 --- /dev/null +++ b/.history/routes/admin_20251022052452.js @@ -0,0 +1,501 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, (req, res) => { + const telegramService = require('../services/telegram'); + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled + }); +}); + +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + await telegramService.sendMessage(testMessage); + + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot + }); + } else { + res.status(400).json({ + success: false, + message: result.message || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +router.post('/telegram/send', requireAuth, async (req, res) => { + try { + const { message } = req.body; + + if (!message || message.trim().length === 0) { + return res.status(400).json({ + success: false, + message: 'Message is required' + }); + } + + const telegramService = require('../services/telegram'); + const result = await telegramService.sendMessage(message); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to send message' + }); + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022194710.js b/.history/routes/admin_20251022194710.js new file mode 100644 index 0000000..60e1cdf --- /dev/null +++ b/.history/routes/admin_20251022194710.js @@ -0,0 +1,717 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, (req, res) => { + const telegramService = require('../services/telegram'); + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled + }); +}); + +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + await telegramService.sendMessage(testMessage); + + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot + }); + } else { + res.status(400).json({ + success: false, + message: result.message || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +router.post('/telegram/send', requireAuth, async (req, res) => { + try { + const { message } = req.body; + + if (!message || message.trim().length === 0) { + return res.status(400).json({ + success: false, + message: 'Message is required' + }); + } + + const telegramService = require('../services/telegram'); + const result = await telegramService.sendMessage(message); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to send message' + }); + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022194741.js b/.history/routes/admin_20251022194741.js new file mode 100644 index 0000000..5d484dc --- /dev/null +++ b/.history/routes/admin_20251022194741.js @@ -0,0 +1,921 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, (req, res) => { + const telegramService = require('../services/telegram'); + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled + }); +}); + +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + await telegramService.sendMessage(testMessage); + + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot + }); + } else { + res.status(400).json({ + success: false, + message: result.message || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +router.post('/telegram/send', requireAuth, async (req, res) => { + try { + const { message } = req.body; + + if (!message || message.trim().length === 0) { + return res.status(400).json({ + success: false, + message: 'Message is required' + }); + } + + const telegramService = require('../services/telegram'); + const result = await telegramService.sendMessage(message); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to send message' + }); + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022194824.js b/.history/routes/admin_20251022194824.js new file mode 100644 index 0000000..db9d7ba --- /dev/null +++ b/.history/routes/admin_20251022194824.js @@ -0,0 +1,921 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner Editor +router.get('/banner-editor', requireAuth, async (req, res) => { + try { + res.render('admin/banner-editor', { + title: 'Редактор Баннеров - Admin Panel', + layout: false, // Отключаем layout для этой страницы + user: req.session.user, + locale: req.getLocale() || 'ko', + theme: req.session.theme || 'light' + }); + } catch (error) { + console.error('Banner editor error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner editor' + }); + } +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, (req, res) => { + const telegramService = require('../services/telegram'); + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled + }); +}); + +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + await telegramService.sendMessage(testMessage); + + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot + }); + } else { + res.status(400).json({ + success: false, + message: result.message || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +router.post('/telegram/send', requireAuth, async (req, res) => { + try { + const { message } = req.body; + + if (!message || message.trim().length === 0) { + return res.status(400).json({ + success: false, + message: 'Message is required' + }); + } + + const telegramService = require('../services/telegram'); + const result = await telegramService.sendMessage(message); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to send message' + }); + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022194900.js b/.history/routes/admin_20251022194900.js new file mode 100644 index 0000000..435a517 --- /dev/null +++ b/.history/routes/admin_20251022194900.js @@ -0,0 +1,1241 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, (req, res) => { + const telegramService = require('../services/telegram'); + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled + }); +}); + +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + await telegramService.sendMessage(testMessage); + + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot + }); + } else { + res.status(400).json({ + success: false, + message: result.message || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +router.post('/telegram/send', requireAuth, async (req, res) => { + try { + const { message } = req.body; + + if (!message || message.trim().length === 0) { + return res.status(400).json({ + success: false, + message: 'Message is required' + }); + } + + const telegramService = require('../services/telegram'); + const result = await telegramService.sendMessage(message); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to send message' + }); + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022195039.js b/.history/routes/admin_20251022195039.js new file mode 100644 index 0000000..bb3e05f --- /dev/null +++ b/.history/routes/admin_20251022195039.js @@ -0,0 +1,1426 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022195541.js b/.history/routes/admin_20251022195541.js new file mode 100644 index 0000000..52890fe --- /dev/null +++ b/.history/routes/admin_20251022195541.js @@ -0,0 +1,1440 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022195905.js b/.history/routes/admin_20251022195905.js new file mode 100644 index 0000000..52890fe --- /dev/null +++ b/.history/routes/admin_20251022195905.js @@ -0,0 +1,1440 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022205401.js b/.history/routes/admin_20251022205401.js new file mode 100644 index 0000000..f9ff0b1 --- /dev/null +++ b/.history/routes/admin_20251022205401.js @@ -0,0 +1,1458 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const sharp = require('sharp'); +const path = require('path'); +const fs = require('fs').promises; +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Configure multer for file uploads +const storage = multer.memoryStorage(); // Use memory storage to process with sharp +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB limit + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed'), false); + } + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('technologies').isArray({ min: 1 }).withMessage('최소 한 개의 기술을 입력해주세요'), +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished = false, + featured = false + } = req.body; + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) ? new Date() : null, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 생성되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022205440.js b/.history/routes/admin_20251022205440.js new file mode 100644 index 0000000..5b3798a --- /dev/null +++ b/.history/routes/admin_20251022205440.js @@ -0,0 +1,1504 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const sharp = require('sharp'); +const path = require('path'); +const fs = require('fs').promises; +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Configure multer for file uploads +const storage = multer.memoryStorage(); // Use memory storage to process with sharp +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB limit + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed'), false); + } + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + if (parsedTechnologies.length === 0) { + return res.status(400).json({ + success: false, + message: 'Добавьте хотя бы одну технологию' + }); + } + + // Process uploaded images + const processedImages = []; + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + processedImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Create portfolio item + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: processedImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) ? new Date() : null, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно создан!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при создании проекта: ' + error.message + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + isPublished, + featured + } = req.body; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: Array.isArray(technologies) ? technologies : technologies.split(',').map(t => t.trim()), + demoUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: Boolean(isPublished), + featured: Boolean(featured), + publishedAt: Boolean(isPublished) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: Boolean(isPublished) ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 업데이트되었습니다', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022205520.js b/.history/routes/admin_20251022205520.js new file mode 100644 index 0000000..c4f4fe6 --- /dev/null +++ b/.history/routes/admin_20251022205520.js @@ -0,0 +1,1552 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const sharp = require('sharp'); +const path = require('path'); +const fs = require('fs').promises; +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Configure multer for file uploads +const storage = multer.memoryStorage(); // Use memory storage to process with sharp +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB limit + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed'), false); + } + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + if (parsedTechnologies.length === 0) { + return res.status(400).json({ + success: false, + message: 'Добавьте хотя бы одну технологию' + }); + } + + // Process uploaded images + const processedImages = []; + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + processedImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Create portfolio item + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: processedImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) ? new Date() : null, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно создан!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при создании проекта: ' + error.message + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: 'Проект не найден' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured, + existingImages + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + // Handle existing images + let finalImages = []; + try { + const existing = JSON.parse(existingImages || '[]'); + finalImages = Array.isArray(existing) ? existing : []; + } catch (e) { + finalImages = portfolio.images || []; + } + + // Process new uploaded images + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + finalImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = portfolio.seo || {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: finalImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно обновлен!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при обновлении проекта: ' + error.message + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022205549.js b/.history/routes/admin_20251022205549.js new file mode 100644 index 0000000..529109a --- /dev/null +++ b/.history/routes/admin_20251022205549.js @@ -0,0 +1,1610 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const sharp = require('sharp'); +const path = require('path'); +const fs = require('fs').promises; +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Configure multer for file uploads +const storage = multer.memoryStorage(); // Use memory storage to process with sharp +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB limit + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed'), false); + } + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + if (parsedTechnologies.length === 0) { + return res.status(400).json({ + success: false, + message: 'Добавьте хотя бы одну технологию' + }); + } + + // Process uploaded images + const processedImages = []; + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + processedImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Create portfolio item + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: processedImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) ? new Date() : null, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно создан!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при создании проекта: ' + error.message + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: 'Проект не найден' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured, + existingImages + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + // Handle existing images + let finalImages = []; + try { + const existing = JSON.parse(existingImages || '[]'); + finalImages = Array.isArray(existing) ? existing : []; + } catch (e) { + finalImages = portfolio.images || []; + } + + // Process new uploaded images + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + finalImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = portfolio.seo || {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: finalImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно обновлен!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при обновлении проекта: ' + error.message + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Portfolio preview +router.post('/portfolio/preview', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName + } = req.body; + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + // Process uploaded images for preview + const previewImages = []; + if (req.files && req.files.length > 0) { + for (const file of req.files) { + // Convert to base64 for preview + const base64 = `data:${file.mimetype};base64,${file.buffer.toString('base64')}`; + previewImages.push(base64); + } + } + + const previewData = { + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: previewImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + createdAt: new Date() + }; + + res.json({ + success: true, + preview: previewData + }); + } catch (error) { + console.error('Portfolio preview error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при создании предпросмотра: ' + error.message + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/admin_20251022211821.js b/.history/routes/admin_20251022211821.js new file mode 100644 index 0000000..529109a --- /dev/null +++ b/.history/routes/admin_20251022211821.js @@ -0,0 +1,1610 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const sharp = require('sharp'); +const path = require('path'); +const fs = require('fs').promises; +const { body, validationResult } = require('express-validator'); +const { User, Portfolio, Service, Contact, SiteSettings, Banner } = require('../models'); + +// Configure multer for file uploads +const storage = multer.memoryStorage(); // Use memory storage to process with sharp +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB limit + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed'), false); + } + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.redirect('/admin/login'); + } + next(); +}; + +// Admin login page +router.get('/login', (req, res) => { + if (req.session.user) { + return res.redirect('/admin/dashboard'); + } + + res.render('admin/login', { + title: 'Admin Login', + error: null + }); +}); + +// Admin login POST +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user || !(await user.comparePassword(password))) { + return res.render('admin/login', { + title: 'Admin Login', + error: 'Invalid credentials' + }); + } + + await user.updateLastLogin(); + + req.session.user = { + id: user.id, + email: user.email, + name: user.name, + role: user.role + }; + + res.redirect('/admin/dashboard'); + } catch (error) { + console.error('Admin login error:', error); + res.render('admin/login', { + title: 'Admin Login', + error: 'Server error' + }); + } +}); + +// Admin logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + console.error('Logout error:', err); + } + res.redirect('/admin/login'); + }); +}); + +// Dashboard (default route) +router.get('/', requireAuth, async (req, res) => { + res.redirect('/admin/dashboard'); +}); + +// Dashboard +router.get('/dashboard', requireAuth, async (req, res) => { + try { + const [ + portfolioCount, + servicesCount, + contactsCount, + recentContacts, + recentPortfolio + ] = await Promise.all([ + Portfolio.count({ where: { isPublished: true } }), + Service.count({ where: { isActive: true } }), + Contact.count(), + Contact.findAll({ + order: [['createdAt', 'DESC']], + limit: 5 + }), + Portfolio.findAll({ + where: { isPublished: true }, + order: [['createdAt', 'DESC']], + limit: 5 + }) + ]); + + const stats = { + portfolioCount: portfolioCount, + servicesCount: servicesCount, + contactsCount: contactsCount, + usersCount: await User.count() + }; + + res.render('admin/dashboard', { + title: 'Admin Dashboard', + layout: 'admin/layout', + user: req.session.user, + stats, + recentContacts, + recentPortfolio + }); + } catch (error) { + console.error('Dashboard error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading dashboard' + }); + } +}); + +// Banner management +router.get('/banners', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [banners, total] = await Promise.all([ + Banner.findAll({ + order: [['order', 'ASC'], ['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Banner.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/banners/list', { + title: 'Banner Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banners, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Banner list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banners' + }); + } +}); + +// Add banner +router.get('/banners/add', requireAuth, (req, res) => { + res.render('admin/banners/add', { + title: 'Add Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); +}); + +// Create banner +router.post('/banners/add', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive = true, + startDate, + endDate, + targetAudience = 'all', + backgroundColor, + textColor, + animation = 'none' + } = req.body; + + const banner = await Banner.create({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience, + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation + }); + + res.json({ + success: true, + message: '배너가 성공적으로 생성되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner creation error:', error); + res.status(500).json({ + success: false, + message: '배너 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit banner +router.get('/banners/edit/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Banner not found' + }); + } + + res.render('admin/banners/edit', { + title: 'Edit Banner - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + banner, + positions: [ + { value: 'hero', label: '메인 히어로' }, + { value: 'secondary', label: '보조 배너' }, + { value: 'footer', label: '푸터 배너' } + ], + animations: [ + { value: 'none', label: '없음' }, + { value: 'fade', label: '페이드' }, + { value: 'slide', label: '슬라이드' }, + { value: 'zoom', label: '줌' } + ] + }); + } catch (error) { + console.error('Banner edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading banner' + }); + } +}); + +// Update banner +router.put('/banners/:id', requireAuth, [ + body('title').notEmpty().withMessage('제목을 입력해주세요'), + body('position').isIn(['hero', 'secondary', 'footer']).withMessage('유효한 위치를 선택해주세요'), + body('order').isInt({ min: 0 }).withMessage('유효한 순서를 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const banner = await Banner.findByPk(req.params.id); + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const { + title, + subtitle, + description, + buttonText, + buttonUrl, + image, + mobileImage, + position, + order, + isActive, + startDate, + endDate, + targetAudience, + backgroundColor, + textColor, + animation + } = req.body; + + await banner.update({ + title, + subtitle: subtitle || null, + description: description || null, + buttonText: buttonText || null, + buttonUrl: buttonUrl || null, + image: image || null, + mobileImage: mobileImage || null, + position, + order: parseInt(order), + isActive: Boolean(isActive), + startDate: startDate || null, + endDate: endDate || null, + targetAudience: targetAudience || 'all', + backgroundColor: backgroundColor || null, + textColor: textColor || null, + animation: animation || 'none' + }); + + res.json({ + success: true, + message: '배너가 성공적으로 업데이트되었습니다', + banner: { + id: banner.id, + title: banner.title, + position: banner.position + } + }); + } catch (error) { + console.error('Banner update error:', error); + res.status(500).json({ + success: false, + message: '배너 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete banner +router.delete('/banners/:id', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.destroy(); + + res.json({ + success: true, + message: '배너가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Banner deletion error:', error); + res.status(500).json({ + success: false, + message: '배너 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle banner active status +router.patch('/banners/:id/toggle-active', requireAuth, async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + const newStatus = !banner.isActive; + await banner.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `배너가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Banner toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Record banner click +router.post('/banners/:id/click', async (req, res) => { + try { + const banner = await Banner.findByPk(req.params.id); + + if (!banner) { + return res.status(404).json({ + success: false, + message: '배너를 찾을 수 없습니다' + }); + } + + await banner.recordClick(); + + res.json({ + success: true, + clickCount: banner.clickCount + }); + } catch (error) { + console.error('Banner click record error:', error); + res.status(500).json({ + success: false, + message: '클릭 기록 중 오류가 발생했습니다' + }); + } +}); + +// Banner Editor (legacy route) +router.get('/banner-editor', requireAuth, async (req, res) => { + res.redirect('/admin/banners'); +}); + +// Portfolio management +router.get('/portfolio', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [portfolio, total] = await Promise.all([ + Portfolio.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Portfolio.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/portfolio/list', { + title: 'Portfolio Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Portfolio list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio' + }); + } +}); + +// Utility function for category names +const getCategoryName = (category) => { + const categoryNames = { + 'web-development': 'Веб-разработка', + 'mobile-app': 'Мобильные приложения', + 'ui-ux-design': 'UI/UX дизайн', + 'e-commerce': 'Электронная коммерция', + 'enterprise': 'Корпоративное ПО', + 'other': 'Другое' + }; + return categoryNames[category] || category; +}; + +// Add portfolio item +router.get('/portfolio/add', requireAuth, (req, res) => { + res.render('admin/portfolio/add', { + title: 'Add Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ], + getCategoryName: getCategoryName + }); +}); + +// Create portfolio item +router.post('/portfolio/add', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + if (parsedTechnologies.length === 0) { + return res.status(400).json({ + success: false, + message: 'Добавьте хотя бы одну технологию' + }); + } + + // Process uploaded images + const processedImages = []; + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + processedImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Create portfolio item + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: processedImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) ? new Date() : null, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно создан!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при создании проекта: ' + error.message + }); + } +}); + +// Edit portfolio item +router.get('/portfolio/edit/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Portfolio item not found' + }); + } + + res.render('admin/portfolio/edit', { + title: 'Edit Portfolio Item - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + portfolio, + categories: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'enterprise', + 'other' + ] + }); + } catch (error) { + console.error('Portfolio edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading portfolio item' + }); + } +}); + +// Update portfolio item +router.put('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ + success: false, + message: 'Проект не найден' + }); + } + + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName, + duration, + seoTitle, + seoDescription, + isPublished, + featured, + existingImages + } = req.body; + + // Validate required fields + if (!title || !shortDescription || !description || !category) { + return res.status(400).json({ + success: false, + message: 'Заполните все обязательные поля' + }); + } + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + // Handle existing images + let finalImages = []; + try { + const existing = JSON.parse(existingImages || '[]'); + finalImages = Array.isArray(existing) ? existing : []; + } catch (e) { + finalImages = portfolio.images || []; + } + + // Process new uploaded images + if (req.files && req.files.length > 0) { + const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'portfolio'); + + // Ensure directory exists + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + + for (const file of req.files) { + const timestamp = Date.now(); + const filename = `${timestamp}-${Math.random().toString(36).substr(2, 9)}.webp`; + const filepath = path.join(uploadDir, filename); + + // Process image with Sharp + await sharp(file.buffer) + .webp({ quality: 85 }) + .resize(1200, 800, { fit: 'inside', withoutEnlargement: true }) + .toFile(filepath); + + finalImages.push(`/uploads/portfolio/${filename}`); + } + } + + // Create SEO data + const seo = portfolio.seo || {}; + if (seoTitle) seo.title = seoTitle; + if (seoDescription) seo.description = seoDescription; + + // Update portfolio + await portfolio.update({ + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: finalImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + duration: duration ? parseInt(duration) : null, + isPublished: isPublished === 'true' || isPublished === true, + featured: featured === 'true' || featured === true, + publishedAt: (isPublished === 'true' || isPublished === true) && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: (isPublished === 'true' || isPublished === true) ? 'published' : 'draft', + seo: Object.keys(seo).length > 0 ? seo : null + }); + + res.json({ + success: true, + message: 'Проект успешно обновлен!', + portfolio: { + id: portfolio.id, + title: portfolio.title, + category: portfolio.category, + isPublished: portfolio.isPublished + } + }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при обновлении проекта: ' + error.message + }); + } +}); + +// Delete portfolio item +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + await portfolio.destroy(); + + res.json({ + success: true, + message: '포트폴리오가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ + success: false, + message: '포트폴리오 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle portfolio publish status +router.patch('/portfolio/:id/toggle-publish', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + + if (!portfolio) { + return res.status(404).json({ + success: false, + message: '포트폴리오를 찾을 수 없습니다' + }); + } + + const newStatus = !portfolio.isPublished; + await portfolio.update({ + isPublished: newStatus, + publishedAt: newStatus && !portfolio.publishedAt ? new Date() : portfolio.publishedAt, + status: newStatus ? 'published' : 'draft' + }); + + res.json({ + success: true, + message: `포트폴리오가 ${newStatus ? '게시' : '비공개'}되었습니다`, + isPublished: newStatus + }); + } catch (error) { + console.error('Portfolio toggle publish error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Portfolio preview +router.post('/portfolio/preview', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + technologies, + demoUrl, + githubUrl, + clientName + } = req.body; + + // Parse technologies from JSON string + let parsedTechnologies = []; + try { + parsedTechnologies = JSON.parse(technologies || '[]'); + } catch (e) { + parsedTechnologies = typeof technologies === 'string' ? [technologies] : []; + } + + // Process uploaded images for preview + const previewImages = []; + if (req.files && req.files.length > 0) { + for (const file of req.files) { + // Convert to base64 for preview + const base64 = `data:${file.mimetype};base64,${file.buffer.toString('base64')}`; + previewImages.push(base64); + } + } + + const previewData = { + title, + shortDescription, + description, + category, + technologies: parsedTechnologies, + images: previewImages, + projectUrl: demoUrl || null, + githubUrl: githubUrl || null, + clientName: clientName || null, + createdAt: new Date() + }; + + res.json({ + success: true, + preview: previewData + }); + } catch (error) { + console.error('Portfolio preview error:', error); + res.status(500).json({ + success: false, + message: 'Ошибка при создании предпросмотра: ' + error.message + }); + } +}); + +// Services management +router.get('/services', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + + const [services, total] = await Promise.all([ + Service.findAll({ + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Service.count() + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/services/list', { + title: 'Services Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + services, + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Services list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading services' + }); + } +}); + +// Add service +router.get('/services/add', requireAuth, (req, res) => { + res.render('admin/services/add', { + title: 'Add Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); +}); + +// Create service +router.post('/services/add', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive = true, + featured = false + } = req.body; + + const service = await Service.create({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 생성되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ + success: false, + message: '서비스 생성 중 오류가 발생했습니다' + }); + } +}); + +// Edit service +router.get('/services/edit/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Service not found' + }); + } + + const availablePortfolio = await Portfolio.findAll({ + where: { isPublished: true }, + attributes: ['id', 'title', 'category'] + }); + + res.render('admin/services/edit', { + title: 'Edit Service - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + service, + availablePortfolio, + serviceTypes: [ + 'web-development', + 'mobile-app', + 'ui-ux-design', + 'e-commerce', + 'seo', + 'maintenance', + 'consultation', + 'other' + ] + }); + } catch (error) { + console.error('Service edit error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading service' + }); + } +}); + +// Update service +router.put('/services/:id', requireAuth, [ + body('name').notEmpty().withMessage('서비스명을 입력해주세요'), + body('shortDescription').notEmpty().withMessage('간단한 설명을 입력해주세요'), + body('description').notEmpty().withMessage('자세한 설명을 입력해주세요'), + body('category').notEmpty().withMessage('카테고리를 선택해주세요'), + body('basePrice').isNumeric().withMessage('기본 가격을 입력해주세요') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: '입력 데이터를 확인해주세요', + errors: errors.array() + }); + } + + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const { + name, + shortDescription, + description, + category, + basePrice, + features, + duration, + isActive, + featured + } = req.body; + + await service.update({ + name, + shortDescription, + description, + category, + basePrice: parseFloat(basePrice), + features: features || [], + duration: duration ? parseInt(duration) : null, + isActive: Boolean(isActive), + featured: Boolean(featured) + }); + + res.json({ + success: true, + message: '서비스가 성공적으로 업데이트되었습니다', + service: { + id: service.id, + name: service.name, + category: service.category + } + }); + } catch (error) { + console.error('Service update error:', error); + res.status(500).json({ + success: false, + message: '서비스 업데이트 중 오류가 발생했습니다' + }); + } +}); + +// Delete service +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + await service.destroy(); + + res.json({ + success: true, + message: '서비스가 성공적으로 삭제되었습니다' + }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ + success: false, + message: '서비스 삭제 중 오류가 발생했습니다' + }); + } +}); + +// Toggle service active status +router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + + if (!service) { + return res.status(404).json({ + success: false, + message: '서비스를 찾을 수 없습니다' + }); + } + + const newStatus = !service.isActive; + await service.update({ isActive: newStatus }); + + res.json({ + success: true, + message: `서비스가 ${newStatus ? '활성화' : '비활성화'}되었습니다`, + isActive: newStatus + }); + } catch (error) { + console.error('Service toggle active error:', error); + res.status(500).json({ + success: false, + message: '상태 변경 중 오류가 발생했습니다' + }); + } +}); + +// Contacts management +router.get('/contacts', requireAuth, async (req, res) => { + try { + const page = parseInt(req.query.page) || 1; + const limit = 20; + const skip = (page - 1) * limit; + const status = req.query.status; + + let whereClause = {}; + if (status && status !== 'all') { + whereClause.status = status; + } + + const [contacts, total] = await Promise.all([ + Contact.findAll({ + where: whereClause, + order: [['createdAt', 'DESC']], + offset: skip, + limit: limit + }), + Contact.count({ where: whereClause }) + ]); + + const totalPages = Math.ceil(total / limit); + + res.render('admin/contacts/list', { + title: 'Contacts Management - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contacts, + currentStatus: status || 'all', + pagination: { + current: page, + total: totalPages, + hasNext: page < totalPages, + hasPrev: page > 1 + } + }); + } catch (error) { + console.error('Contacts list error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contacts' + }); + } +}); + +// View contact details +router.get('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + + if (!contact) { + return res.status(404).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Contact not found' + }); + } + + // Mark as read + if (!contact.isRead) { + contact.isRead = true; + await contact.save(); + } + + res.render('admin/contacts/view', { + title: 'Contact Details - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + contact + }); + } catch (error) { + console.error('Contact view error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading contact' + }); + } +}); + +// Settings +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || await SiteSettings.create({}); + + res.render('admin/settings', { + title: 'Site Settings - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + settings + }); + } catch (error) { + console.error('Settings error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading settings' + }); + } +}); + +// Media gallery +router.get('/media', requireAuth, (req, res) => { + res.render('admin/media', { + title: 'Media Gallery - Admin Panel', + layout: 'admin/layout', + user: req.session.user + }); +}); + +// Telegram bot configuration and testing +router.get('/telegram', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + + // Get bot info and available chats if token is configured + let botInfo = null; + let availableChats = []; + + if (telegramService.botToken) { + const result = await telegramService.getBotInfo(); + if (result.success) { + botInfo = result.bot; + availableChats = telegramService.getAvailableChats(); + } + } + + res.render('admin/telegram', { + title: 'Telegram Bot - Admin Panel', + layout: 'admin/layout', + user: req.session.user, + botConfigured: telegramService.isEnabled, + botToken: telegramService.botToken || '', + chatId: telegramService.chatId || '', + botInfo, + availableChats + }); + } catch (error) { + console.error('Telegram page error:', error); + res.status(500).render('admin/error', { + title: 'Error - Admin Panel', + layout: 'admin/layout', + message: 'Error loading Telegram settings' + }); + } +}); + +// Update bot token +router.post('/telegram/configure', requireAuth, [ + body('botToken').notEmpty().withMessage('Bot token is required'), + body('chatId').optional().isNumeric().withMessage('Chat ID must be numeric') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { botToken, chatId } = req.body; + const telegramService = require('../services/telegram'); + + // Update bot token + const result = await telegramService.updateBotToken(botToken); + + if (result.success) { + // Update chat ID if provided + if (chatId) { + telegramService.updateChatId(parseInt(chatId)); + } + + // Update environment variables (in production, this should update a config file) + process.env.TELEGRAM_BOT_TOKEN = botToken; + if (chatId) { + process.env.TELEGRAM_CHAT_ID = chatId; + } + + res.json({ + success: true, + message: 'Telegram bot configured successfully', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to configure bot' + }); + } + } catch (error) { + console.error('Configure Telegram bot error:', error); + res.status(500).json({ + success: false, + message: 'Error configuring Telegram bot' + }); + } +}); + +// Get bot info and discover chats +router.get('/telegram/info', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + res.json({ + success: true, + botInfo: result.bot, + availableChats: result.availableChats || [], + isConfigured: telegramService.isEnabled + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to get bot info' + }); + } + } catch (error) { + console.error('Get Telegram info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting bot information' + }); + } +}); + +// Get chat information +router.get('/telegram/chat/:chatId', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.getChat(req.params.chatId); + + if (result.success) { + res.json({ + success: true, + chat: result.chat + }); + } else { + res.status(400).json({ + success: false, + message: result.error || 'Failed to get chat info' + }); + } + } catch (error) { + console.error('Get chat info error:', error); + res.status(500).json({ + success: false, + message: 'Error getting chat information' + }); + } +}); + +// Test connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const telegramService = require('../services/telegram'); + const result = await telegramService.testConnection(); + + if (result.success) { + const testMessage = `🤖 Тест Telegram бота\n\n` + + `✅ Соединение успешно установлено!\n` + + `🤖 Бот: @${result.bot.username} (${result.bot.first_name})\n` + + `🆔 ID бота: ${result.bot.id}\n` + + `⏰ Время тестирования: ${new Date().toLocaleString('ru-RU')}\n` + + `🌐 Сайт: ${process.env.BASE_URL || 'http://localhost:3000'}\n\n` + + `Бот готов к отправке уведомлений! 🚀`; + + const sendResult = await telegramService.sendMessage(testMessage); + + if (sendResult.success) { + res.json({ + success: true, + message: 'Test message sent successfully!', + botInfo: result.bot, + availableChats: result.availableChats || [] + }); + } else { + res.status(400).json({ + success: false, + message: 'Bot connection successful, but failed to send test message: ' + (sendResult.error || sendResult.message) + }); + } + } else { + res.status(400).json({ + success: false, + message: result.message || result.error || 'Failed to connect to Telegram bot' + }); + } + } catch (error) { + console.error('Telegram test error:', error); + res.status(500).json({ + success: false, + message: 'Error testing Telegram bot' + }); + } +}); + +// Send custom message +router.post('/telegram/send', requireAuth, [ + body('message').notEmpty().withMessage('Message is required'), + body('chatIds').optional().isArray().withMessage('Chat IDs must be an array'), + body('parseMode').optional().isIn(['HTML', 'Markdown', 'MarkdownV2']).withMessage('Invalid parse mode') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Validation failed', + errors: errors.array() + }); + } + + const { + message, + chatIds = [], + parseMode = 'HTML', + disableWebPagePreview = false, + disableNotification = false + } = req.body; + + const telegramService = require('../services/telegram'); + + let result; + if (chatIds.length > 0) { + // Send to multiple chats + result = await telegramService.sendCustomMessage({ + text: message, + chatIds: chatIds.map(id => parseInt(id)), + parseMode, + disableWebPagePreview, + disableNotification + }); + + res.json({ + success: result.success, + message: result.success ? + `Message sent to ${result.totalSent} chat(s). ${result.totalFailed} failed.` : + 'Failed to send message', + results: result.results || [], + errors: result.errors || [] + }); + } else { + // Send to default chat + result = await telegramService.sendMessage(message, { + parse_mode: parseMode, + disable_web_page_preview: disableWebPagePreview, + disable_notification: disableNotification + }); + + if (result.success) { + res.json({ + success: true, + message: 'Message sent successfully!' + }); + } else { + res.status(400).json({ + success: false, + message: result.error || result.message || 'Failed to send message' + }); + } + } + } catch (error) { + console.error('Send Telegram message error:', error); + res.status(500).json({ + success: false, + message: 'Error sending message' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/api/admin_20251021213116.js b/.history/routes/api/admin_20251021213116.js new file mode 100644 index 0000000..e0cd2cb --- /dev/null +++ b/.history/routes/api/admin_20251021213116.js @@ -0,0 +1,284 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const path = require('path'); +const { Portfolio, Service, Contact, User } = require('../../models'); + +// Multer configuration for file uploads +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, 'public/uploads/'); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); + cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); + } +}); + +const upload = multer({ + storage: storage, + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed!'), false); + } + }, + limits: { + fileSize: 10 * 1024 * 1024 // 10MB + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.status(401).json({ success: false, message: 'Authentication required' }); + } + next(); +}; + +// Portfolio API Routes +router.post('/portfolio', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + clientName, + projectUrl, + githubUrl, + technologies, + featured, + isPublished + } = req.body; + + // Process uploaded images + const images = req.files ? req.files.map((file, index) => ({ + url: `/uploads/${file.filename}`, + alt: `${title} image ${index + 1}`, + isPrimary: index === 0 + })) : []; + + // Parse technologies + let techArray = []; + if (technologies) { + try { + techArray = JSON.parse(technologies); + } catch (e) { + techArray = technologies.split(',').map(t => t.trim()); + } + } + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + clientName, + projectUrl: projectUrl || null, + githubUrl: githubUrl || null, + technologies: techArray, + images, + featured: featured === 'on', + isPublished: isPublished === 'on', + status: 'completed', + publishedAt: isPublished === 'on' ? new Date() : null + }); + + res.json({ success: true, portfolio }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.patch('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ success: false, message: 'Portfolio not found' }); + } + + const updates = { ...req.body }; + + // Handle checkboxes + updates.featured = updates.featured === 'on'; + updates.isPublished = updates.isPublished === 'on'; + + // Process technologies + if (updates.technologies) { + try { + updates.technologies = JSON.parse(updates.technologies); + } catch (e) { + updates.technologies = updates.technologies.split(',').map(t => t.trim()); + } + } + + // Process new images + if (req.files && req.files.length > 0) { + const newImages = req.files.map((file, index) => ({ + url: `/uploads/${file.filename}`, + alt: `${updates.title || portfolio.title} image ${index + 1}`, + isPrimary: index === 0 && (!portfolio.images || portfolio.images.length === 0) + })); + + updates.images = [...(portfolio.images || []), ...newImages]; + } + + await portfolio.update(updates); + res.json({ success: true, portfolio }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ success: false, message: 'Portfolio not found' }); + } + + await portfolio.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Services API Routes +router.post('/services', requireAuth, async (req, res) => { + try { + const { + name, + description, + shortDescription, + icon, + category, + features, + pricing, + estimatedTime, + isActive, + featured, + tags + } = req.body; + + // Parse arrays + let featuresArray = []; + let tagsArray = []; + let pricingObj = {}; + + if (features) { + try { + featuresArray = JSON.parse(features); + } catch (e) { + featuresArray = features.split(',').map(f => f.trim()); + } + } + + if (tags) { + try { + tagsArray = JSON.parse(tags); + } catch (e) { + tagsArray = tags.split(',').map(t => t.trim()); + } + } + + if (pricing) { + try { + pricingObj = JSON.parse(pricing); + } catch (e) { + pricingObj = { basePrice: pricing }; + } + } + + const service = await Service.create({ + name, + description, + shortDescription, + icon, + category, + features: featuresArray, + pricing: pricingObj, + estimatedTime, + isActive: isActive === 'on', + featured: featured === 'on', + tags: tagsArray + }); + + res.json({ success: true, service }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ success: false, message: 'Service not found' }); + } + + await service.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Contacts API Routes +router.patch('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + await contact.update(req.body); + res.json({ success: true, contact }); + } catch (error) { + console.error('Contact update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + await contact.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Contact deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Telegram notification for contact +router.post('/contacts/:id/telegram', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + // Send Telegram notification (we'll implement this with Telegram bot) + const telegramService = require('../../services/telegram'); + await telegramService.sendContactNotification(contact); + + res.json({ success: true }); + } catch (error) { + console.error('Telegram notification error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/api/admin_20251021213414.js b/.history/routes/api/admin_20251021213414.js new file mode 100644 index 0000000..f7fc941 --- /dev/null +++ b/.history/routes/api/admin_20251021213414.js @@ -0,0 +1,388 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const path = require('path'); +const { Portfolio, Service, Contact, User } = require('../../models'); + +// Multer configuration for file uploads +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, 'public/uploads/'); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); + cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); + } +}); + +const upload = multer({ + storage: storage, + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed!'), false); + } + }, + limits: { + fileSize: 10 * 1024 * 1024 // 10MB + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.status(401).json({ success: false, message: 'Authentication required' }); + } + next(); +}; + +// Portfolio API Routes +router.post('/portfolio', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + clientName, + projectUrl, + githubUrl, + technologies, + featured, + isPublished + } = req.body; + + // Process uploaded images + const images = req.files ? req.files.map((file, index) => ({ + url: `/uploads/${file.filename}`, + alt: `${title} image ${index + 1}`, + isPrimary: index === 0 + })) : []; + + // Parse technologies + let techArray = []; + if (technologies) { + try { + techArray = JSON.parse(technologies); + } catch (e) { + techArray = technologies.split(',').map(t => t.trim()); + } + } + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + clientName, + projectUrl: projectUrl || null, + githubUrl: githubUrl || null, + technologies: techArray, + images, + featured: featured === 'on', + isPublished: isPublished === 'on', + status: 'completed', + publishedAt: isPublished === 'on' ? new Date() : null + }); + + res.json({ success: true, portfolio }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.patch('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ success: false, message: 'Portfolio not found' }); + } + + const updates = { ...req.body }; + + // Handle checkboxes + updates.featured = updates.featured === 'on'; + updates.isPublished = updates.isPublished === 'on'; + + // Process technologies + if (updates.technologies) { + try { + updates.technologies = JSON.parse(updates.technologies); + } catch (e) { + updates.technologies = updates.technologies.split(',').map(t => t.trim()); + } + } + + // Process new images + if (req.files && req.files.length > 0) { + const newImages = req.files.map((file, index) => ({ + url: `/uploads/${file.filename}`, + alt: `${updates.title || portfolio.title} image ${index + 1}`, + isPrimary: index === 0 && (!portfolio.images || portfolio.images.length === 0) + })); + + updates.images = [...(portfolio.images || []), ...newImages]; + } + + await portfolio.update(updates); + res.json({ success: true, portfolio }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ success: false, message: 'Portfolio not found' }); + } + + await portfolio.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Services API Routes +router.post('/services', requireAuth, async (req, res) => { + try { + const { + name, + description, + shortDescription, + icon, + category, + features, + pricing, + estimatedTime, + isActive, + featured, + tags + } = req.body; + + // Parse arrays + let featuresArray = []; + let tagsArray = []; + let pricingObj = {}; + + if (features) { + try { + featuresArray = JSON.parse(features); + } catch (e) { + featuresArray = features.split(',').map(f => f.trim()); + } + } + + if (tags) { + try { + tagsArray = JSON.parse(tags); + } catch (e) { + tagsArray = tags.split(',').map(t => t.trim()); + } + } + + if (pricing) { + try { + pricingObj = JSON.parse(pricing); + } catch (e) { + pricingObj = { basePrice: pricing }; + } + } + + const service = await Service.create({ + name, + description, + shortDescription, + icon, + category, + features: featuresArray, + pricing: pricingObj, + estimatedTime, + isActive: isActive === 'on', + featured: featured === 'on', + tags: tagsArray + }); + + res.json({ success: true, service }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ success: false, message: 'Service not found' }); + } + + await service.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Contacts API Routes +router.patch('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + await contact.update(req.body); + res.json({ success: true, contact }); + } catch (error) { + console.error('Contact update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + await contact.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Contact deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Telegram notification for contact +router.post('/contacts/:id/telegram', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + // Send Telegram notification + const telegramService = require('../../services/telegram'); + const result = await telegramService.sendContactNotification(contact); + + if (result.success) { + res.json({ success: true }); + } else { + res.status(500).json({ success: false, message: result.message || result.error }); + } + } catch (error) { + console.error('Telegram notification error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Test Telegram connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const { botToken, chatId } = req.body; + + // Temporarily set up telegram service with provided credentials + const axios = require('axios'); + + // Test bot info + const botResponse = await axios.get(`https://api.telegram.org/bot${botToken}/getMe`); + + // Test sending a message + const testMessage = '✅ Telegram bot подключен успешно!\n\nЭто тестовое сообщение от SmartSolTech Admin Panel.'; + await axios.post(`https://api.telegram.org/bot${botToken}/sendMessage`, { + chat_id: chatId, + text: testMessage, + parse_mode: 'Markdown' + }); + + res.json({ + success: true, + bot: botResponse.data.result, + message: 'Test message sent successfully' + }); + } catch (error) { + console.error('Telegram test error:', error); + let message = 'Connection failed'; + + if (error.response?.data?.description) { + message = error.response.data.description; + } else if (error.message) { + message = error.message; + } + + res.status(400).json({ success: false, message }); + } +}); + +// Settings API +const { SiteSettings } = require('../../models'); + +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || {}; + res.json({ success: true, settings }); + } catch (error) { + console.error('Settings fetch error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.post('/settings', requireAuth, upload.fields([ + { name: 'logo', maxCount: 1 }, + { name: 'favicon', maxCount: 1 } +]), async (req, res) => { + try { + let settings = await SiteSettings.findOne(); + if (!settings) { + settings = await SiteSettings.create({}); + } + + const updates = {}; + + // Handle nested objects + Object.keys(req.body).forEach(key => { + if (key.includes('.')) { + const [parent, child] = key.split('.'); + if (!updates[parent]) updates[parent] = {}; + updates[parent][child] = req.body[key]; + } else { + updates[key] = req.body[key]; + } + }); + + // Handle file uploads + if (req.files.logo) { + updates.logo = `/uploads/${req.files.logo[0].filename}`; + } + if (req.files.favicon) { + updates.favicon = `/uploads/${req.files.favicon[0].filename}`; + } + + // Update existing settings with new values + Object.keys(updates).forEach(key => { + if (typeof updates[key] === 'object' && updates[key] !== null) { + settings[key] = { ...settings[key], ...updates[key] }; + } else { + settings[key] = updates[key]; + } + }); + + await settings.save(); + + res.json({ success: true, settings }); + } catch (error) { + console.error('Settings update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/api/admin_20251021214113.js b/.history/routes/api/admin_20251021214113.js new file mode 100644 index 0000000..f7fc941 --- /dev/null +++ b/.history/routes/api/admin_20251021214113.js @@ -0,0 +1,388 @@ +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const path = require('path'); +const { Portfolio, Service, Contact, User } = require('../../models'); + +// Multer configuration for file uploads +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, 'public/uploads/'); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); + cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); + } +}); + +const upload = multer({ + storage: storage, + fileFilter: (req, file, cb) => { + if (file.mimetype.startsWith('image/')) { + cb(null, true); + } else { + cb(new Error('Only image files are allowed!'), false); + } + }, + limits: { + fileSize: 10 * 1024 * 1024 // 10MB + } +}); + +// Authentication middleware +const requireAuth = (req, res, next) => { + if (!req.session.user) { + return res.status(401).json({ success: false, message: 'Authentication required' }); + } + next(); +}; + +// Portfolio API Routes +router.post('/portfolio', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const { + title, + shortDescription, + description, + category, + clientName, + projectUrl, + githubUrl, + technologies, + featured, + isPublished + } = req.body; + + // Process uploaded images + const images = req.files ? req.files.map((file, index) => ({ + url: `/uploads/${file.filename}`, + alt: `${title} image ${index + 1}`, + isPrimary: index === 0 + })) : []; + + // Parse technologies + let techArray = []; + if (technologies) { + try { + techArray = JSON.parse(technologies); + } catch (e) { + techArray = technologies.split(',').map(t => t.trim()); + } + } + + const portfolio = await Portfolio.create({ + title, + shortDescription, + description, + category, + clientName, + projectUrl: projectUrl || null, + githubUrl: githubUrl || null, + technologies: techArray, + images, + featured: featured === 'on', + isPublished: isPublished === 'on', + status: 'completed', + publishedAt: isPublished === 'on' ? new Date() : null + }); + + res.json({ success: true, portfolio }); + } catch (error) { + console.error('Portfolio creation error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.patch('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ success: false, message: 'Portfolio not found' }); + } + + const updates = { ...req.body }; + + // Handle checkboxes + updates.featured = updates.featured === 'on'; + updates.isPublished = updates.isPublished === 'on'; + + // Process technologies + if (updates.technologies) { + try { + updates.technologies = JSON.parse(updates.technologies); + } catch (e) { + updates.technologies = updates.technologies.split(',').map(t => t.trim()); + } + } + + // Process new images + if (req.files && req.files.length > 0) { + const newImages = req.files.map((file, index) => ({ + url: `/uploads/${file.filename}`, + alt: `${updates.title || portfolio.title} image ${index + 1}`, + isPrimary: index === 0 && (!portfolio.images || portfolio.images.length === 0) + })); + + updates.images = [...(portfolio.images || []), ...newImages]; + } + + await portfolio.update(updates); + res.json({ success: true, portfolio }); + } catch (error) { + console.error('Portfolio update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/portfolio/:id', requireAuth, async (req, res) => { + try { + const portfolio = await Portfolio.findByPk(req.params.id); + if (!portfolio) { + return res.status(404).json({ success: false, message: 'Portfolio not found' }); + } + + await portfolio.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Portfolio deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Services API Routes +router.post('/services', requireAuth, async (req, res) => { + try { + const { + name, + description, + shortDescription, + icon, + category, + features, + pricing, + estimatedTime, + isActive, + featured, + tags + } = req.body; + + // Parse arrays + let featuresArray = []; + let tagsArray = []; + let pricingObj = {}; + + if (features) { + try { + featuresArray = JSON.parse(features); + } catch (e) { + featuresArray = features.split(',').map(f => f.trim()); + } + } + + if (tags) { + try { + tagsArray = JSON.parse(tags); + } catch (e) { + tagsArray = tags.split(',').map(t => t.trim()); + } + } + + if (pricing) { + try { + pricingObj = JSON.parse(pricing); + } catch (e) { + pricingObj = { basePrice: pricing }; + } + } + + const service = await Service.create({ + name, + description, + shortDescription, + icon, + category, + features: featuresArray, + pricing: pricingObj, + estimatedTime, + isActive: isActive === 'on', + featured: featured === 'on', + tags: tagsArray + }); + + res.json({ success: true, service }); + } catch (error) { + console.error('Service creation error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/services/:id', requireAuth, async (req, res) => { + try { + const service = await Service.findByPk(req.params.id); + if (!service) { + return res.status(404).json({ success: false, message: 'Service not found' }); + } + + await service.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Service deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Contacts API Routes +router.patch('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + await contact.update(req.body); + res.json({ success: true, contact }); + } catch (error) { + console.error('Contact update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.delete('/contacts/:id', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + await contact.destroy(); + res.json({ success: true }); + } catch (error) { + console.error('Contact deletion error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Telegram notification for contact +router.post('/contacts/:id/telegram', requireAuth, async (req, res) => { + try { + const contact = await Contact.findByPk(req.params.id); + if (!contact) { + return res.status(404).json({ success: false, message: 'Contact not found' }); + } + + // Send Telegram notification + const telegramService = require('../../services/telegram'); + const result = await telegramService.sendContactNotification(contact); + + if (result.success) { + res.json({ success: true }); + } else { + res.status(500).json({ success: false, message: result.message || result.error }); + } + } catch (error) { + console.error('Telegram notification error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +// Test Telegram connection +router.post('/telegram/test', requireAuth, async (req, res) => { + try { + const { botToken, chatId } = req.body; + + // Temporarily set up telegram service with provided credentials + const axios = require('axios'); + + // Test bot info + const botResponse = await axios.get(`https://api.telegram.org/bot${botToken}/getMe`); + + // Test sending a message + const testMessage = '✅ Telegram bot подключен успешно!\n\nЭто тестовое сообщение от SmartSolTech Admin Panel.'; + await axios.post(`https://api.telegram.org/bot${botToken}/sendMessage`, { + chat_id: chatId, + text: testMessage, + parse_mode: 'Markdown' + }); + + res.json({ + success: true, + bot: botResponse.data.result, + message: 'Test message sent successfully' + }); + } catch (error) { + console.error('Telegram test error:', error); + let message = 'Connection failed'; + + if (error.response?.data?.description) { + message = error.response.data.description; + } else if (error.message) { + message = error.message; + } + + res.status(400).json({ success: false, message }); + } +}); + +// Settings API +const { SiteSettings } = require('../../models'); + +router.get('/settings', requireAuth, async (req, res) => { + try { + const settings = await SiteSettings.findOne() || {}; + res.json({ success: true, settings }); + } catch (error) { + console.error('Settings fetch error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +router.post('/settings', requireAuth, upload.fields([ + { name: 'logo', maxCount: 1 }, + { name: 'favicon', maxCount: 1 } +]), async (req, res) => { + try { + let settings = await SiteSettings.findOne(); + if (!settings) { + settings = await SiteSettings.create({}); + } + + const updates = {}; + + // Handle nested objects + Object.keys(req.body).forEach(key => { + if (key.includes('.')) { + const [parent, child] = key.split('.'); + if (!updates[parent]) updates[parent] = {}; + updates[parent][child] = req.body[key]; + } else { + updates[key] = req.body[key]; + } + }); + + // Handle file uploads + if (req.files.logo) { + updates.logo = `/uploads/${req.files.logo[0].filename}`; + } + if (req.files.favicon) { + updates.favicon = `/uploads/${req.files.favicon[0].filename}`; + } + + // Update existing settings with new values + Object.keys(updates).forEach(key => { + if (typeof updates[key] === 'object' && updates[key] !== null) { + settings[key] = { ...settings[key], ...updates[key] }; + } else { + settings[key] = updates[key]; + } + }); + + await settings.save(); + + res.json({ success: true, settings }); + } catch (error) { + console.error('Settings update error:', error); + res.status(500).json({ success: false, message: error.message }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/auth_20251019204627.js b/.history/routes/auth_20251019204627.js new file mode 100644 index 0000000..7363fcf --- /dev/null +++ b/.history/routes/auth_20251019204627.js @@ -0,0 +1,201 @@ +const express = require('express'); +const router = express.Router(); +const jwt = require('jsonwebtoken'); +const { body, validationResult } = require('express-validator'); +const { User } = require('../models'); + +// Login validation rules +const loginValidation = [ + body('email').isEmail().normalizeEmail(), + body('password').isLength({ min: 6 }) +]; + +// Login +router.post('/login', loginValidation, async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { email, password } = req.body; + + // Find user + const user = await User.findOne({ email, isActive: true }); + if (!user) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Check password + const isValidPassword = await user.comparePassword(password); + if (!isValidPassword) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Update last login + await user.updateLastLogin(); + + // Create JWT token + const token = jwt.sign( + { userId: user._id, email: user.email, role: user.role }, + process.env.JWT_SECRET, + { expiresIn: '7d' } + ); + + // Set session + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.json({ + success: true, + message: 'Login successful', + token, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar + } + }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + return res.status(500).json({ + success: false, + message: 'Could not log out' + }); + } + + res.clearCookie('connect.sid'); + res.json({ + success: true, + message: 'Logout successful' + }); + }); +}); + +// Check authentication status +router.get('/me', async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const user = await User.findById(req.session.user.id) + .select('-password'); + + if (!user || !user.isActive) { + req.session.destroy(); + return res.status(401).json({ + success: false, + message: 'User not found or inactive' + }); + } + + res.json({ + success: true, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar, + lastLogin: user.lastLogin + } + }); + } catch (error) { + console.error('Auth check error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Change password +router.put('/change-password', [ + body('currentPassword').isLength({ min: 6 }), + body('newPassword').isLength({ min: 6 }) +], async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { currentPassword, newPassword } = req.body; + const user = await User.findById(req.session.user.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: 'User not found' + }); + } + + // Verify current password + const isValidPassword = await user.comparePassword(currentPassword); + if (!isValidPassword) { + return res.status(400).json({ + success: false, + message: 'Current password is incorrect' + }); + } + + // Update password + user.password = newPassword; + await user.save(); + + res.json({ + success: true, + message: 'Password updated successfully' + }); + } catch (error) { + console.error('Change password error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/auth_20251019204633.js b/.history/routes/auth_20251019204633.js new file mode 100644 index 0000000..790c0b2 --- /dev/null +++ b/.history/routes/auth_20251019204633.js @@ -0,0 +1,206 @@ +const express = require('express'); +const router = express.Router(); +const jwt = require('jsonwebtoken'); +const { body, validationResult } = require('express-validator'); +const { User } = require('../models'); + +// Login validation rules +const loginValidation = [ + body('email').isEmail().normalizeEmail(), + body('password').isLength({ min: 6 }) +]; + +// Login +router.post('/login', loginValidation, async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { email, password } = req.body; + + // Find user + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Check password + const isValidPassword = await user.comparePassword(password); + if (!isValidPassword) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Update last login + await user.updateLastLogin(); + + // Create JWT token + const token = jwt.sign( + { userId: user._id, email: user.email, role: user.role }, + process.env.JWT_SECRET, + { expiresIn: '7d' } + ); + + // Set session + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.json({ + success: true, + message: 'Login successful', + token, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar + } + }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + return res.status(500).json({ + success: false, + message: 'Could not log out' + }); + } + + res.clearCookie('connect.sid'); + res.json({ + success: true, + message: 'Logout successful' + }); + }); +}); + +// Check authentication status +router.get('/me', async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const user = await User.findById(req.session.user.id) + .select('-password'); + + if (!user || !user.isActive) { + req.session.destroy(); + return res.status(401).json({ + success: false, + message: 'User not found or inactive' + }); + } + + res.json({ + success: true, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar, + lastLogin: user.lastLogin + } + }); + } catch (error) { + console.error('Auth check error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Change password +router.put('/change-password', [ + body('currentPassword').isLength({ min: 6 }), + body('newPassword').isLength({ min: 6 }) +], async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { currentPassword, newPassword } = req.body; + const user = await User.findById(req.session.user.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: 'User not found' + }); + } + + // Verify current password + const isValidPassword = await user.comparePassword(currentPassword); + if (!isValidPassword) { + return res.status(400).json({ + success: false, + message: 'Current password is incorrect' + }); + } + + // Update password + user.password = newPassword; + await user.save(); + + res.json({ + success: true, + message: 'Password updated successfully' + }); + } catch (error) { + console.error('Change password error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/auth_20251019204648.js b/.history/routes/auth_20251019204648.js new file mode 100644 index 0000000..87df84d --- /dev/null +++ b/.history/routes/auth_20251019204648.js @@ -0,0 +1,207 @@ +const express = require('express'); +const router = express.Router(); +const jwt = require('jsonwebtoken'); +const { body, validationResult } = require('express-validator'); +const { User } = require('../models'); + +// Login validation rules +const loginValidation = [ + body('email').isEmail().normalizeEmail(), + body('password').isLength({ min: 6 }) +]; + +// Login +router.post('/login', loginValidation, async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { email, password } = req.body; + + // Find user + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Check password + const isValidPassword = await user.comparePassword(password); + if (!isValidPassword) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Update last login + await user.updateLastLogin(); + + // Create JWT token + const token = jwt.sign( + { userId: user._id, email: user.email, role: user.role }, + process.env.JWT_SECRET, + { expiresIn: '7d' } + ); + + // Set session + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.json({ + success: true, + message: 'Login successful', + token, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar + } + }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + return res.status(500).json({ + success: false, + message: 'Could not log out' + }); + } + + res.clearCookie('connect.sid'); + res.json({ + success: true, + message: 'Logout successful' + }); + }); +}); + +// Check authentication status +router.get('/me', async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const user = await User.findByPk(req.session.user.id, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + req.session.destroy(); + return res.status(401).json({ + success: false, + message: 'User not found or inactive' + }); + } + + res.json({ + success: true, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar, + lastLogin: user.lastLogin + } + }); + } catch (error) { + console.error('Auth check error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Change password +router.put('/change-password', [ + body('currentPassword').isLength({ min: 6 }), + body('newPassword').isLength({ min: 6 }) +], async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { currentPassword, newPassword } = req.body; + const user = await User.findById(req.session.user.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: 'User not found' + }); + } + + // Verify current password + const isValidPassword = await user.comparePassword(currentPassword); + if (!isValidPassword) { + return res.status(400).json({ + success: false, + message: 'Current password is incorrect' + }); + } + + // Update password + user.password = newPassword; + await user.save(); + + res.json({ + success: true, + message: 'Password updated successfully' + }); + } catch (error) { + console.error('Change password error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/auth_20251019204658.js b/.history/routes/auth_20251019204658.js new file mode 100644 index 0000000..7a71b05 --- /dev/null +++ b/.history/routes/auth_20251019204658.js @@ -0,0 +1,207 @@ +const express = require('express'); +const router = express.Router(); +const jwt = require('jsonwebtoken'); +const { body, validationResult } = require('express-validator'); +const { User } = require('../models'); + +// Login validation rules +const loginValidation = [ + body('email').isEmail().normalizeEmail(), + body('password').isLength({ min: 6 }) +]; + +// Login +router.post('/login', loginValidation, async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { email, password } = req.body; + + // Find user + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Check password + const isValidPassword = await user.comparePassword(password); + if (!isValidPassword) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Update last login + await user.updateLastLogin(); + + // Create JWT token + const token = jwt.sign( + { userId: user._id, email: user.email, role: user.role }, + process.env.JWT_SECRET, + { expiresIn: '7d' } + ); + + // Set session + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.json({ + success: true, + message: 'Login successful', + token, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar + } + }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + return res.status(500).json({ + success: false, + message: 'Could not log out' + }); + } + + res.clearCookie('connect.sid'); + res.json({ + success: true, + message: 'Logout successful' + }); + }); +}); + +// Check authentication status +router.get('/me', async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const user = await User.findByPk(req.session.user.id, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + req.session.destroy(); + return res.status(401).json({ + success: false, + message: 'User not found or inactive' + }); + } + + res.json({ + success: true, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar, + lastLogin: user.lastLogin + } + }); + } catch (error) { + console.error('Auth check error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Change password +router.put('/change-password', [ + body('currentPassword').isLength({ min: 6 }), + body('newPassword').isLength({ min: 6 }) +], async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { currentPassword, newPassword } = req.body; + const user = await User.findByPk(req.session.user.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: 'User not found' + }); + } + + // Verify current password + const isValidPassword = await user.comparePassword(currentPassword); + if (!isValidPassword) { + return res.status(400).json({ + success: false, + message: 'Current password is incorrect' + }); + } + + // Update password + user.password = newPassword; + await user.save(); + + res.json({ + success: true, + message: 'Password updated successfully' + }); + } catch (error) { + console.error('Change password error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/auth_20251019204806.js b/.history/routes/auth_20251019204806.js new file mode 100644 index 0000000..7a71b05 --- /dev/null +++ b/.history/routes/auth_20251019204806.js @@ -0,0 +1,207 @@ +const express = require('express'); +const router = express.Router(); +const jwt = require('jsonwebtoken'); +const { body, validationResult } = require('express-validator'); +const { User } = require('../models'); + +// Login validation rules +const loginValidation = [ + body('email').isEmail().normalizeEmail(), + body('password').isLength({ min: 6 }) +]; + +// Login +router.post('/login', loginValidation, async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { email, password } = req.body; + + // Find user + const user = await User.findOne({ + where: { + email: email, + isActive: true + } + }); + if (!user) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Check password + const isValidPassword = await user.comparePassword(password); + if (!isValidPassword) { + return res.status(401).json({ + success: false, + message: 'Invalid credentials' + }); + } + + // Update last login + await user.updateLastLogin(); + + // Create JWT token + const token = jwt.sign( + { userId: user._id, email: user.email, role: user.role }, + process.env.JWT_SECRET, + { expiresIn: '7d' } + ); + + // Set session + req.session.user = { + id: user._id, + email: user.email, + name: user.name, + role: user.role + }; + + res.json({ + success: true, + message: 'Login successful', + token, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar + } + }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Logout +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + return res.status(500).json({ + success: false, + message: 'Could not log out' + }); + } + + res.clearCookie('connect.sid'); + res.json({ + success: true, + message: 'Logout successful' + }); + }); +}); + +// Check authentication status +router.get('/me', async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const user = await User.findByPk(req.session.user.id, { + attributes: { exclude: ['password'] } + }); + + if (!user || !user.isActive) { + req.session.destroy(); + return res.status(401).json({ + success: false, + message: 'User not found or inactive' + }); + } + + res.json({ + success: true, + user: { + id: user._id, + email: user.email, + name: user.name, + role: user.role, + avatar: user.avatar, + lastLogin: user.lastLogin + } + }); + } catch (error) { + console.error('Auth check error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +// Change password +router.put('/change-password', [ + body('currentPassword').isLength({ min: 6 }), + body('newPassword').isLength({ min: 6 }) +], async (req, res) => { + try { + if (!req.session.user) { + return res.status(401).json({ + success: false, + message: 'Not authenticated' + }); + } + + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { currentPassword, newPassword } = req.body; + const user = await User.findByPk(req.session.user.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: 'User not found' + }); + } + + // Verify current password + const isValidPassword = await user.comparePassword(currentPassword); + if (!isValidPassword) { + return res.status(400).json({ + success: false, + message: 'Current password is incorrect' + }); + } + + // Update password + user.password = newPassword; + await user.save(); + + res.json({ + success: true, + message: 'Password updated successfully' + }); + } catch (error) { + console.error('Change password error:', error); + res.status(500).json({ + success: false, + message: 'Server error' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/calculator_20251019204545.js b/.history/routes/calculator_20251019204545.js new file mode 100644 index 0000000..38732f0 --- /dev/null +++ b/.history/routes/calculator_20251019204545.js @@ -0,0 +1,312 @@ +const express = require('express'); +const router = express.Router(); +const { Service } = require('../models'); + +// Get all services for calculator +router.get('/services', async (req, res) => { + try { + const services = await Service.find({ isActive: true }) + .select('name pricing category features estimatedTime') + .sort({ category: 1, name: 1 }); + + const servicesByCategory = services.reduce((acc, service) => { + if (!acc[service.category]) { + acc[service.category] = []; + } + acc[service.category].push(service); + return acc; + }, {}); + + res.json({ + success: true, + services: servicesByCategory, + allServices: services + }); + } catch (error) { + console.error('Calculator services error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching services' + }); + } +}); + +// Calculate project estimate +router.post('/calculate', async (req, res) => { + try { + const { + selectedServices = [], + projectComplexity = 'medium', + timeline = 'standard', + additionalFeatures = [], + customRequirements = '' + } = req.body; + + if (!selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Please select at least one service' + }); + } + + // Get selected services details + const services = await Service.find({ + _id: { $in: selectedServices }, + isActive: true + }); + + if (services.length !== selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Some selected services are not available' + }); + } + + // Calculate base cost + let baseCost = 0; + let totalTime = 0; // in days + + services.forEach(service => { + baseCost += service.pricing.basePrice; + totalTime += (service.estimatedTime.min + service.estimatedTime.max) / 2; + }); + + // Apply complexity multiplier + const complexityMultipliers = { + 'simple': 0.7, + 'medium': 1.0, + 'complex': 1.5, + 'enterprise': 2.0 + }; + + const complexityMultiplier = complexityMultipliers[projectComplexity] || 1.0; + + // Apply timeline multiplier + const timelineMultipliers = { + 'rush': 1.8, // Less than 2 weeks + 'fast': 1.4, // 2-4 weeks + 'standard': 1.0, // 1-3 months + 'flexible': 0.8 // 3+ months + }; + + const timelineMultiplier = timelineMultipliers[timeline] || 1.0; + + // Additional features cost + const featureCosts = { + 'seo-optimization': 300000, + 'analytics-setup': 150000, + 'social-integration': 200000, + 'payment-gateway': 500000, + 'multilingual': 400000, + 'admin-panel': 600000, + 'api-integration': 350000, + 'mobile-responsive': 250000, + 'ssl-certificate': 100000, + 'backup-system': 200000 + }; + + let additionalCost = 0; + additionalFeatures.forEach(feature => { + additionalCost += featureCosts[feature] || 0; + }); + + // Custom requirements cost (estimated based on description length and complexity) + let customCost = 0; + if (customRequirements && customRequirements.length > 50) { + customCost = Math.min(customRequirements.length * 1000, 1000000); // Max 1M KRW + } + + // Calculate final estimate + const subtotal = baseCost * complexityMultiplier * timelineMultiplier; + const total = subtotal + additionalCost + customCost; + + // Calculate time estimate + const timeMultiplier = complexityMultiplier * timelineMultiplier; + const estimatedDays = Math.ceil(totalTime * timeMultiplier); + const estimatedWeeks = Math.ceil(estimatedDays / 7); + + // Create price ranges (±20%) + const minPrice = Math.round(total * 0.8); + const maxPrice = Math.round(total * 1.2); + + // Breakdown + const breakdown = { + baseServices: Math.round(baseCost), + complexityAdjustment: Math.round(baseCost * (complexityMultiplier - 1)), + timelineAdjustment: Math.round(baseCost * complexityMultiplier * (timelineMultiplier - 1)), + additionalFeatures: additionalCost, + customRequirements: customCost, + subtotal: Math.round(subtotal), + total: Math.round(total) + }; + + const result = { + success: true, + estimate: { + total: Math.round(total), + range: { + min: minPrice, + max: maxPrice, + formatted: `₩${minPrice.toLocaleString()} - ₩${maxPrice.toLocaleString()}` + }, + breakdown, + timeline: { + days: estimatedDays, + weeks: estimatedWeeks, + formatted: estimatedWeeks === 1 ? '1 week' : `${estimatedWeeks} weeks` + }, + currency: 'KRW', + confidence: calculateConfidence(services.length, projectComplexity, customRequirements), + recommendations: generateRecommendations(projectComplexity, timeline, services) + }, + selectedServices: services.map(s => ({ + id: s._id, + name: s.name, + category: s.category, + basePrice: s.pricing.basePrice + })), + calculatedAt: new Date() + }; + + res.json(result); + } catch (error) { + console.error('Calculator calculation error:', error); + res.status(500).json({ + success: false, + message: 'Error calculating estimate' + }); + } +}); + +// Helper function to calculate confidence level +function calculateConfidence(serviceCount, complexity, customRequirements) { + let confidence = 85; // Base confidence + + // Adjust based on service count + if (serviceCount === 1) confidence += 10; + else if (serviceCount > 5) confidence -= 10; + + // Adjust based on complexity + if (complexity === 'simple') confidence += 10; + else if (complexity === 'enterprise') confidence -= 15; + + // Adjust based on custom requirements + if (customRequirements && customRequirements.length > 200) { + confidence -= 20; + } + + return Math.max(60, Math.min(95, confidence)); +} + +// Helper function to generate recommendations +function generateRecommendations(complexity, timeline, services) { + const recommendations = []; + + if (complexity === 'enterprise' && timeline === 'rush') { + recommendations.push('Consider extending timeline for enterprise-level projects to ensure quality'); + } + + if (services.length > 6) { + recommendations.push('Consider breaking down into phases for better project management'); + } + + if (timeline === 'flexible') { + recommendations.push('Flexible timeline allows for better cost optimization and quality assurance'); + } + + const hasDesign = services.some(s => s.category === 'design'); + const hasDevelopment = services.some(s => s.category === 'development'); + + if (hasDevelopment && !hasDesign) { + recommendations.push('Consider adding UI/UX design services for better user experience'); + } + + return recommendations; +} + +// Get pricing guidelines +router.get('/pricing-guide', async (req, res) => { + try { + const pricingGuide = { + serviceCategories: { + 'development': { + name: 'Web Development', + priceRange: '₩500,000 - ₩5,000,000', + description: 'Custom web applications and websites' + }, + 'design': { + name: 'UI/UX Design', + priceRange: '₩300,000 - ₩2,000,000', + description: 'User interface and experience design' + }, + 'marketing': { + name: 'Digital Marketing', + priceRange: '₩200,000 - ₩1,500,000', + description: 'SEO, social media, and online marketing' + }, + 'consulting': { + name: 'Technical Consulting', + priceRange: '₩150,000 - ₩1,000,000', + description: 'Technology strategy and consultation' + } + }, + complexityFactors: { + 'simple': { + name: 'Simple Project', + multiplier: '0.7x', + description: 'Basic functionality, standard design' + }, + 'medium': { + name: 'Medium Project', + multiplier: '1.0x', + description: 'Moderate complexity, custom features' + }, + 'complex': { + name: 'Complex Project', + multiplier: '1.5x', + description: 'Advanced features, integrations' + }, + 'enterprise': { + name: 'Enterprise Project', + multiplier: '2.0x', + description: 'Large scale, high complexity' + } + }, + timelineImpact: { + 'rush': { + name: 'Rush (< 2 weeks)', + multiplier: '+80%', + description: 'Requires overtime and priority handling' + }, + 'fast': { + name: 'Fast (2-4 weeks)', + multiplier: '+40%', + description: 'Accelerated timeline' + }, + 'standard': { + name: 'Standard (1-3 months)', + multiplier: 'Standard', + description: 'Normal project timeline' + }, + 'flexible': { + name: 'Flexible (3+ months)', + multiplier: '-20%', + description: 'Extended timeline allows optimization' + } + } + }; + + res.json({ + success: true, + pricingGuide + }); + } catch (error) { + console.error('Pricing guide error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching pricing guide' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/calculator_20251019204551.js b/.history/routes/calculator_20251019204551.js new file mode 100644 index 0000000..cb31511 --- /dev/null +++ b/.history/routes/calculator_20251019204551.js @@ -0,0 +1,314 @@ +const express = require('express'); +const router = express.Router(); +const { Service } = require('../models'); + +// Get all services for calculator +router.get('/services', async (req, res) => { + try { + const services = await Service.findAll({ + where: { isActive: true }, + attributes: ['id', 'name', 'pricing', 'category', 'features', 'estimatedTime'], + order: [['category', 'ASC'], ['name', 'ASC']] + }); + + const servicesByCategory = services.reduce((acc, service) => { + if (!acc[service.category]) { + acc[service.category] = []; + } + acc[service.category].push(service); + return acc; + }, {}); + + res.json({ + success: true, + services: servicesByCategory, + allServices: services + }); + } catch (error) { + console.error('Calculator services error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching services' + }); + } +}); + +// Calculate project estimate +router.post('/calculate', async (req, res) => { + try { + const { + selectedServices = [], + projectComplexity = 'medium', + timeline = 'standard', + additionalFeatures = [], + customRequirements = '' + } = req.body; + + if (!selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Please select at least one service' + }); + } + + // Get selected services details + const services = await Service.find({ + _id: { $in: selectedServices }, + isActive: true + }); + + if (services.length !== selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Some selected services are not available' + }); + } + + // Calculate base cost + let baseCost = 0; + let totalTime = 0; // in days + + services.forEach(service => { + baseCost += service.pricing.basePrice; + totalTime += (service.estimatedTime.min + service.estimatedTime.max) / 2; + }); + + // Apply complexity multiplier + const complexityMultipliers = { + 'simple': 0.7, + 'medium': 1.0, + 'complex': 1.5, + 'enterprise': 2.0 + }; + + const complexityMultiplier = complexityMultipliers[projectComplexity] || 1.0; + + // Apply timeline multiplier + const timelineMultipliers = { + 'rush': 1.8, // Less than 2 weeks + 'fast': 1.4, // 2-4 weeks + 'standard': 1.0, // 1-3 months + 'flexible': 0.8 // 3+ months + }; + + const timelineMultiplier = timelineMultipliers[timeline] || 1.0; + + // Additional features cost + const featureCosts = { + 'seo-optimization': 300000, + 'analytics-setup': 150000, + 'social-integration': 200000, + 'payment-gateway': 500000, + 'multilingual': 400000, + 'admin-panel': 600000, + 'api-integration': 350000, + 'mobile-responsive': 250000, + 'ssl-certificate': 100000, + 'backup-system': 200000 + }; + + let additionalCost = 0; + additionalFeatures.forEach(feature => { + additionalCost += featureCosts[feature] || 0; + }); + + // Custom requirements cost (estimated based on description length and complexity) + let customCost = 0; + if (customRequirements && customRequirements.length > 50) { + customCost = Math.min(customRequirements.length * 1000, 1000000); // Max 1M KRW + } + + // Calculate final estimate + const subtotal = baseCost * complexityMultiplier * timelineMultiplier; + const total = subtotal + additionalCost + customCost; + + // Calculate time estimate + const timeMultiplier = complexityMultiplier * timelineMultiplier; + const estimatedDays = Math.ceil(totalTime * timeMultiplier); + const estimatedWeeks = Math.ceil(estimatedDays / 7); + + // Create price ranges (±20%) + const minPrice = Math.round(total * 0.8); + const maxPrice = Math.round(total * 1.2); + + // Breakdown + const breakdown = { + baseServices: Math.round(baseCost), + complexityAdjustment: Math.round(baseCost * (complexityMultiplier - 1)), + timelineAdjustment: Math.round(baseCost * complexityMultiplier * (timelineMultiplier - 1)), + additionalFeatures: additionalCost, + customRequirements: customCost, + subtotal: Math.round(subtotal), + total: Math.round(total) + }; + + const result = { + success: true, + estimate: { + total: Math.round(total), + range: { + min: minPrice, + max: maxPrice, + formatted: `₩${minPrice.toLocaleString()} - ₩${maxPrice.toLocaleString()}` + }, + breakdown, + timeline: { + days: estimatedDays, + weeks: estimatedWeeks, + formatted: estimatedWeeks === 1 ? '1 week' : `${estimatedWeeks} weeks` + }, + currency: 'KRW', + confidence: calculateConfidence(services.length, projectComplexity, customRequirements), + recommendations: generateRecommendations(projectComplexity, timeline, services) + }, + selectedServices: services.map(s => ({ + id: s._id, + name: s.name, + category: s.category, + basePrice: s.pricing.basePrice + })), + calculatedAt: new Date() + }; + + res.json(result); + } catch (error) { + console.error('Calculator calculation error:', error); + res.status(500).json({ + success: false, + message: 'Error calculating estimate' + }); + } +}); + +// Helper function to calculate confidence level +function calculateConfidence(serviceCount, complexity, customRequirements) { + let confidence = 85; // Base confidence + + // Adjust based on service count + if (serviceCount === 1) confidence += 10; + else if (serviceCount > 5) confidence -= 10; + + // Adjust based on complexity + if (complexity === 'simple') confidence += 10; + else if (complexity === 'enterprise') confidence -= 15; + + // Adjust based on custom requirements + if (customRequirements && customRequirements.length > 200) { + confidence -= 20; + } + + return Math.max(60, Math.min(95, confidence)); +} + +// Helper function to generate recommendations +function generateRecommendations(complexity, timeline, services) { + const recommendations = []; + + if (complexity === 'enterprise' && timeline === 'rush') { + recommendations.push('Consider extending timeline for enterprise-level projects to ensure quality'); + } + + if (services.length > 6) { + recommendations.push('Consider breaking down into phases for better project management'); + } + + if (timeline === 'flexible') { + recommendations.push('Flexible timeline allows for better cost optimization and quality assurance'); + } + + const hasDesign = services.some(s => s.category === 'design'); + const hasDevelopment = services.some(s => s.category === 'development'); + + if (hasDevelopment && !hasDesign) { + recommendations.push('Consider adding UI/UX design services for better user experience'); + } + + return recommendations; +} + +// Get pricing guidelines +router.get('/pricing-guide', async (req, res) => { + try { + const pricingGuide = { + serviceCategories: { + 'development': { + name: 'Web Development', + priceRange: '₩500,000 - ₩5,000,000', + description: 'Custom web applications and websites' + }, + 'design': { + name: 'UI/UX Design', + priceRange: '₩300,000 - ₩2,000,000', + description: 'User interface and experience design' + }, + 'marketing': { + name: 'Digital Marketing', + priceRange: '₩200,000 - ₩1,500,000', + description: 'SEO, social media, and online marketing' + }, + 'consulting': { + name: 'Technical Consulting', + priceRange: '₩150,000 - ₩1,000,000', + description: 'Technology strategy and consultation' + } + }, + complexityFactors: { + 'simple': { + name: 'Simple Project', + multiplier: '0.7x', + description: 'Basic functionality, standard design' + }, + 'medium': { + name: 'Medium Project', + multiplier: '1.0x', + description: 'Moderate complexity, custom features' + }, + 'complex': { + name: 'Complex Project', + multiplier: '1.5x', + description: 'Advanced features, integrations' + }, + 'enterprise': { + name: 'Enterprise Project', + multiplier: '2.0x', + description: 'Large scale, high complexity' + } + }, + timelineImpact: { + 'rush': { + name: 'Rush (< 2 weeks)', + multiplier: '+80%', + description: 'Requires overtime and priority handling' + }, + 'fast': { + name: 'Fast (2-4 weeks)', + multiplier: '+40%', + description: 'Accelerated timeline' + }, + 'standard': { + name: 'Standard (1-3 months)', + multiplier: 'Standard', + description: 'Normal project timeline' + }, + 'flexible': { + name: 'Flexible (3+ months)', + multiplier: '-20%', + description: 'Extended timeline allows optimization' + } + } + }; + + res.json({ + success: true, + pricingGuide + }); + } catch (error) { + console.error('Pricing guide error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching pricing guide' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/calculator_20251019204602.js b/.history/routes/calculator_20251019204602.js new file mode 100644 index 0000000..d701cda --- /dev/null +++ b/.history/routes/calculator_20251019204602.js @@ -0,0 +1,316 @@ +const express = require('express'); +const router = express.Router(); +const { Service } = require('../models'); + +// Get all services for calculator +router.get('/services', async (req, res) => { + try { + const services = await Service.findAll({ + where: { isActive: true }, + attributes: ['id', 'name', 'pricing', 'category', 'features', 'estimatedTime'], + order: [['category', 'ASC'], ['name', 'ASC']] + }); + + const servicesByCategory = services.reduce((acc, service) => { + if (!acc[service.category]) { + acc[service.category] = []; + } + acc[service.category].push(service); + return acc; + }, {}); + + res.json({ + success: true, + services: servicesByCategory, + allServices: services + }); + } catch (error) { + console.error('Calculator services error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching services' + }); + } +}); + +// Calculate project estimate +router.post('/calculate', async (req, res) => { + try { + const { + selectedServices = [], + projectComplexity = 'medium', + timeline = 'standard', + additionalFeatures = [], + customRequirements = '' + } = req.body; + + if (!selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Please select at least one service' + }); + } + + // Get selected services details + const services = await Service.findAll({ + where: { + id: selectedServices, + isActive: true + } + }); + + if (services.length !== selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Some selected services are not available' + }); + } + + // Calculate base cost + let baseCost = 0; + let totalTime = 0; // in days + + services.forEach(service => { + baseCost += service.pricing.basePrice; + totalTime += (service.estimatedTime.min + service.estimatedTime.max) / 2; + }); + + // Apply complexity multiplier + const complexityMultipliers = { + 'simple': 0.7, + 'medium': 1.0, + 'complex': 1.5, + 'enterprise': 2.0 + }; + + const complexityMultiplier = complexityMultipliers[projectComplexity] || 1.0; + + // Apply timeline multiplier + const timelineMultipliers = { + 'rush': 1.8, // Less than 2 weeks + 'fast': 1.4, // 2-4 weeks + 'standard': 1.0, // 1-3 months + 'flexible': 0.8 // 3+ months + }; + + const timelineMultiplier = timelineMultipliers[timeline] || 1.0; + + // Additional features cost + const featureCosts = { + 'seo-optimization': 300000, + 'analytics-setup': 150000, + 'social-integration': 200000, + 'payment-gateway': 500000, + 'multilingual': 400000, + 'admin-panel': 600000, + 'api-integration': 350000, + 'mobile-responsive': 250000, + 'ssl-certificate': 100000, + 'backup-system': 200000 + }; + + let additionalCost = 0; + additionalFeatures.forEach(feature => { + additionalCost += featureCosts[feature] || 0; + }); + + // Custom requirements cost (estimated based on description length and complexity) + let customCost = 0; + if (customRequirements && customRequirements.length > 50) { + customCost = Math.min(customRequirements.length * 1000, 1000000); // Max 1M KRW + } + + // Calculate final estimate + const subtotal = baseCost * complexityMultiplier * timelineMultiplier; + const total = subtotal + additionalCost + customCost; + + // Calculate time estimate + const timeMultiplier = complexityMultiplier * timelineMultiplier; + const estimatedDays = Math.ceil(totalTime * timeMultiplier); + const estimatedWeeks = Math.ceil(estimatedDays / 7); + + // Create price ranges (±20%) + const minPrice = Math.round(total * 0.8); + const maxPrice = Math.round(total * 1.2); + + // Breakdown + const breakdown = { + baseServices: Math.round(baseCost), + complexityAdjustment: Math.round(baseCost * (complexityMultiplier - 1)), + timelineAdjustment: Math.round(baseCost * complexityMultiplier * (timelineMultiplier - 1)), + additionalFeatures: additionalCost, + customRequirements: customCost, + subtotal: Math.round(subtotal), + total: Math.round(total) + }; + + const result = { + success: true, + estimate: { + total: Math.round(total), + range: { + min: minPrice, + max: maxPrice, + formatted: `₩${minPrice.toLocaleString()} - ₩${maxPrice.toLocaleString()}` + }, + breakdown, + timeline: { + days: estimatedDays, + weeks: estimatedWeeks, + formatted: estimatedWeeks === 1 ? '1 week' : `${estimatedWeeks} weeks` + }, + currency: 'KRW', + confidence: calculateConfidence(services.length, projectComplexity, customRequirements), + recommendations: generateRecommendations(projectComplexity, timeline, services) + }, + selectedServices: services.map(s => ({ + id: s._id, + name: s.name, + category: s.category, + basePrice: s.pricing.basePrice + })), + calculatedAt: new Date() + }; + + res.json(result); + } catch (error) { + console.error('Calculator calculation error:', error); + res.status(500).json({ + success: false, + message: 'Error calculating estimate' + }); + } +}); + +// Helper function to calculate confidence level +function calculateConfidence(serviceCount, complexity, customRequirements) { + let confidence = 85; // Base confidence + + // Adjust based on service count + if (serviceCount === 1) confidence += 10; + else if (serviceCount > 5) confidence -= 10; + + // Adjust based on complexity + if (complexity === 'simple') confidence += 10; + else if (complexity === 'enterprise') confidence -= 15; + + // Adjust based on custom requirements + if (customRequirements && customRequirements.length > 200) { + confidence -= 20; + } + + return Math.max(60, Math.min(95, confidence)); +} + +// Helper function to generate recommendations +function generateRecommendations(complexity, timeline, services) { + const recommendations = []; + + if (complexity === 'enterprise' && timeline === 'rush') { + recommendations.push('Consider extending timeline for enterprise-level projects to ensure quality'); + } + + if (services.length > 6) { + recommendations.push('Consider breaking down into phases for better project management'); + } + + if (timeline === 'flexible') { + recommendations.push('Flexible timeline allows for better cost optimization and quality assurance'); + } + + const hasDesign = services.some(s => s.category === 'design'); + const hasDevelopment = services.some(s => s.category === 'development'); + + if (hasDevelopment && !hasDesign) { + recommendations.push('Consider adding UI/UX design services for better user experience'); + } + + return recommendations; +} + +// Get pricing guidelines +router.get('/pricing-guide', async (req, res) => { + try { + const pricingGuide = { + serviceCategories: { + 'development': { + name: 'Web Development', + priceRange: '₩500,000 - ₩5,000,000', + description: 'Custom web applications and websites' + }, + 'design': { + name: 'UI/UX Design', + priceRange: '₩300,000 - ₩2,000,000', + description: 'User interface and experience design' + }, + 'marketing': { + name: 'Digital Marketing', + priceRange: '₩200,000 - ₩1,500,000', + description: 'SEO, social media, and online marketing' + }, + 'consulting': { + name: 'Technical Consulting', + priceRange: '₩150,000 - ₩1,000,000', + description: 'Technology strategy and consultation' + } + }, + complexityFactors: { + 'simple': { + name: 'Simple Project', + multiplier: '0.7x', + description: 'Basic functionality, standard design' + }, + 'medium': { + name: 'Medium Project', + multiplier: '1.0x', + description: 'Moderate complexity, custom features' + }, + 'complex': { + name: 'Complex Project', + multiplier: '1.5x', + description: 'Advanced features, integrations' + }, + 'enterprise': { + name: 'Enterprise Project', + multiplier: '2.0x', + description: 'Large scale, high complexity' + } + }, + timelineImpact: { + 'rush': { + name: 'Rush (< 2 weeks)', + multiplier: '+80%', + description: 'Requires overtime and priority handling' + }, + 'fast': { + name: 'Fast (2-4 weeks)', + multiplier: '+40%', + description: 'Accelerated timeline' + }, + 'standard': { + name: 'Standard (1-3 months)', + multiplier: 'Standard', + description: 'Normal project timeline' + }, + 'flexible': { + name: 'Flexible (3+ months)', + multiplier: '-20%', + description: 'Extended timeline allows optimization' + } + } + }; + + res.json({ + success: true, + pricingGuide + }); + } catch (error) { + console.error('Pricing guide error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching pricing guide' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/calculator_20251019204805.js b/.history/routes/calculator_20251019204805.js new file mode 100644 index 0000000..d701cda --- /dev/null +++ b/.history/routes/calculator_20251019204805.js @@ -0,0 +1,316 @@ +const express = require('express'); +const router = express.Router(); +const { Service } = require('../models'); + +// Get all services for calculator +router.get('/services', async (req, res) => { + try { + const services = await Service.findAll({ + where: { isActive: true }, + attributes: ['id', 'name', 'pricing', 'category', 'features', 'estimatedTime'], + order: [['category', 'ASC'], ['name', 'ASC']] + }); + + const servicesByCategory = services.reduce((acc, service) => { + if (!acc[service.category]) { + acc[service.category] = []; + } + acc[service.category].push(service); + return acc; + }, {}); + + res.json({ + success: true, + services: servicesByCategory, + allServices: services + }); + } catch (error) { + console.error('Calculator services error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching services' + }); + } +}); + +// Calculate project estimate +router.post('/calculate', async (req, res) => { + try { + const { + selectedServices = [], + projectComplexity = 'medium', + timeline = 'standard', + additionalFeatures = [], + customRequirements = '' + } = req.body; + + if (!selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Please select at least one service' + }); + } + + // Get selected services details + const services = await Service.findAll({ + where: { + id: selectedServices, + isActive: true + } + }); + + if (services.length !== selectedServices.length) { + return res.status(400).json({ + success: false, + message: 'Some selected services are not available' + }); + } + + // Calculate base cost + let baseCost = 0; + let totalTime = 0; // in days + + services.forEach(service => { + baseCost += service.pricing.basePrice; + totalTime += (service.estimatedTime.min + service.estimatedTime.max) / 2; + }); + + // Apply complexity multiplier + const complexityMultipliers = { + 'simple': 0.7, + 'medium': 1.0, + 'complex': 1.5, + 'enterprise': 2.0 + }; + + const complexityMultiplier = complexityMultipliers[projectComplexity] || 1.0; + + // Apply timeline multiplier + const timelineMultipliers = { + 'rush': 1.8, // Less than 2 weeks + 'fast': 1.4, // 2-4 weeks + 'standard': 1.0, // 1-3 months + 'flexible': 0.8 // 3+ months + }; + + const timelineMultiplier = timelineMultipliers[timeline] || 1.0; + + // Additional features cost + const featureCosts = { + 'seo-optimization': 300000, + 'analytics-setup': 150000, + 'social-integration': 200000, + 'payment-gateway': 500000, + 'multilingual': 400000, + 'admin-panel': 600000, + 'api-integration': 350000, + 'mobile-responsive': 250000, + 'ssl-certificate': 100000, + 'backup-system': 200000 + }; + + let additionalCost = 0; + additionalFeatures.forEach(feature => { + additionalCost += featureCosts[feature] || 0; + }); + + // Custom requirements cost (estimated based on description length and complexity) + let customCost = 0; + if (customRequirements && customRequirements.length > 50) { + customCost = Math.min(customRequirements.length * 1000, 1000000); // Max 1M KRW + } + + // Calculate final estimate + const subtotal = baseCost * complexityMultiplier * timelineMultiplier; + const total = subtotal + additionalCost + customCost; + + // Calculate time estimate + const timeMultiplier = complexityMultiplier * timelineMultiplier; + const estimatedDays = Math.ceil(totalTime * timeMultiplier); + const estimatedWeeks = Math.ceil(estimatedDays / 7); + + // Create price ranges (±20%) + const minPrice = Math.round(total * 0.8); + const maxPrice = Math.round(total * 1.2); + + // Breakdown + const breakdown = { + baseServices: Math.round(baseCost), + complexityAdjustment: Math.round(baseCost * (complexityMultiplier - 1)), + timelineAdjustment: Math.round(baseCost * complexityMultiplier * (timelineMultiplier - 1)), + additionalFeatures: additionalCost, + customRequirements: customCost, + subtotal: Math.round(subtotal), + total: Math.round(total) + }; + + const result = { + success: true, + estimate: { + total: Math.round(total), + range: { + min: minPrice, + max: maxPrice, + formatted: `₩${minPrice.toLocaleString()} - ₩${maxPrice.toLocaleString()}` + }, + breakdown, + timeline: { + days: estimatedDays, + weeks: estimatedWeeks, + formatted: estimatedWeeks === 1 ? '1 week' : `${estimatedWeeks} weeks` + }, + currency: 'KRW', + confidence: calculateConfidence(services.length, projectComplexity, customRequirements), + recommendations: generateRecommendations(projectComplexity, timeline, services) + }, + selectedServices: services.map(s => ({ + id: s._id, + name: s.name, + category: s.category, + basePrice: s.pricing.basePrice + })), + calculatedAt: new Date() + }; + + res.json(result); + } catch (error) { + console.error('Calculator calculation error:', error); + res.status(500).json({ + success: false, + message: 'Error calculating estimate' + }); + } +}); + +// Helper function to calculate confidence level +function calculateConfidence(serviceCount, complexity, customRequirements) { + let confidence = 85; // Base confidence + + // Adjust based on service count + if (serviceCount === 1) confidence += 10; + else if (serviceCount > 5) confidence -= 10; + + // Adjust based on complexity + if (complexity === 'simple') confidence += 10; + else if (complexity === 'enterprise') confidence -= 15; + + // Adjust based on custom requirements + if (customRequirements && customRequirements.length > 200) { + confidence -= 20; + } + + return Math.max(60, Math.min(95, confidence)); +} + +// Helper function to generate recommendations +function generateRecommendations(complexity, timeline, services) { + const recommendations = []; + + if (complexity === 'enterprise' && timeline === 'rush') { + recommendations.push('Consider extending timeline for enterprise-level projects to ensure quality'); + } + + if (services.length > 6) { + recommendations.push('Consider breaking down into phases for better project management'); + } + + if (timeline === 'flexible') { + recommendations.push('Flexible timeline allows for better cost optimization and quality assurance'); + } + + const hasDesign = services.some(s => s.category === 'design'); + const hasDevelopment = services.some(s => s.category === 'development'); + + if (hasDevelopment && !hasDesign) { + recommendations.push('Consider adding UI/UX design services for better user experience'); + } + + return recommendations; +} + +// Get pricing guidelines +router.get('/pricing-guide', async (req, res) => { + try { + const pricingGuide = { + serviceCategories: { + 'development': { + name: 'Web Development', + priceRange: '₩500,000 - ₩5,000,000', + description: 'Custom web applications and websites' + }, + 'design': { + name: 'UI/UX Design', + priceRange: '₩300,000 - ₩2,000,000', + description: 'User interface and experience design' + }, + 'marketing': { + name: 'Digital Marketing', + priceRange: '₩200,000 - ₩1,500,000', + description: 'SEO, social media, and online marketing' + }, + 'consulting': { + name: 'Technical Consulting', + priceRange: '₩150,000 - ₩1,000,000', + description: 'Technology strategy and consultation' + } + }, + complexityFactors: { + 'simple': { + name: 'Simple Project', + multiplier: '0.7x', + description: 'Basic functionality, standard design' + }, + 'medium': { + name: 'Medium Project', + multiplier: '1.0x', + description: 'Moderate complexity, custom features' + }, + 'complex': { + name: 'Complex Project', + multiplier: '1.5x', + description: 'Advanced features, integrations' + }, + 'enterprise': { + name: 'Enterprise Project', + multiplier: '2.0x', + description: 'Large scale, high complexity' + } + }, + timelineImpact: { + 'rush': { + name: 'Rush (< 2 weeks)', + multiplier: '+80%', + description: 'Requires overtime and priority handling' + }, + 'fast': { + name: 'Fast (2-4 weeks)', + multiplier: '+40%', + description: 'Accelerated timeline' + }, + 'standard': { + name: 'Standard (1-3 months)', + multiplier: 'Standard', + description: 'Normal project timeline' + }, + 'flexible': { + name: 'Flexible (3+ months)', + multiplier: '-20%', + description: 'Extended timeline allows optimization' + } + } + }; + + res.json({ + success: true, + pricingGuide + }); + } catch (error) { + console.error('Pricing guide error:', error); + res.status(500).json({ + success: false, + message: 'Error fetching pricing guide' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/.history/routes/contact_20251019204616.js b/.history/routes/contact_20251019204616.js new file mode 100644 index 0000000..4bb8161 --- /dev/null +++ b/.history/routes/contact_20251019204616.js @@ -0,0 +1,250 @@ +const express = require('express'); +const router = express.Router(); +const { body, validationResult } = require('express-validator'); +const nodemailer = require('nodemailer'); +const { Contact } = require('../models'); +const TelegramBot = require('node-telegram-bot-api'); + +// Initialize Telegram bot if token is provided +let bot = null; +if (process.env.TELEGRAM_BOT_TOKEN) { + bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, { polling: false }); +} + +// Contact form validation +const contactValidation = [ + body('name').trim().isLength({ min: 2, max: 100 }), + body('email').isEmail().normalizeEmail(), + body('subject').trim().isLength({ min: 5, max: 200 }), + body('message').trim().isLength({ min: 10, max: 2000 }), + body('phone').optional().isMobilePhone(), + body('company').optional().trim().isLength({ max: 100 }) +]; + +// Submit contact form +router.post('/submit', contactValidation, async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const contactData = { + ...req.body, + ipAddress: req.ip, + userAgent: req.get('User-Agent'), + source: 'website' + }; + + // Save to database + const contact = new Contact(contactData); + await contact.save(); + + // Send email notification + await sendEmailNotification(contact); + + // Send Telegram notification + await sendTelegramNotification(contact); + + res.json({ + success: true, + message: 'Your message has been sent successfully. We will get back to you soon!', + contactId: contact._id + }); + } catch (error) { + console.error('Contact form error:', error); + res.status(500).json({ + success: false, + message: 'Sorry, there was an error sending your message. Please try again.' + }); + } +}); + +// Get project estimate +router.post('/estimate', [ + body('services').isArray().notEmpty(), + body('projectType').notEmpty(), + body('timeline').notEmpty(), + body('budget').notEmpty(), + body('description').trim().isLength({ min: 10, max: 1000 }) +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + success: false, + message: 'Invalid input data', + errors: errors.array() + }); + } + + const { services, projectType, timeline, budget, description, contactInfo } = req.body; + + // Calculate estimate (simplified) + const estimate = calculateProjectEstimate(services, projectType, timeline); + + // Save inquiry to database + const contactData = { + name: contactInfo.name, + email: contactInfo.email, + phone: contactInfo.phone, + company: contactInfo.company, + subject: `Project Estimate Request - ${projectType}`, + message: `Project Description: ${description}\n\nServices: ${services.join(', ')}\nTimeline: ${timeline}\nBudget: ${budget}\n\nCalculated Estimate: ${estimate.formatted}`, + serviceInterest: projectType, + budget: budget, + timeline: timeline, + source: 'calculator', + ipAddress: req.ip, + userAgent: req.get('User-Agent') + }; + + const contact = new Contact(contactData); + await contact.save(); + + // Send notifications + await sendEmailNotification(contact); + await sendTelegramNotification(contact); + + res.json({ + success: true, + message: 'Your project estimate request has been submitted successfully!', + estimate: estimate, + contactId: contact._id + }); + } catch (error) { + console.error('Estimate request error:', error); + res.status(500).json({ + success: false, + message: 'Sorry, there was an error processing your request. Please try again.' + }); + } +}); + +// Helper function to send email notification +async function sendEmailNotification(contact) { + if (!process.env.EMAIL_HOST || !process.env.EMAIL_USER) { + console.log('Email configuration not provided, skipping email notification'); + return; + } + + try { + const transporter = nodemailer.createTransporter({ + host: process.env.EMAIL_HOST, + port: process.env.EMAIL_PORT || 587, + secure: false, + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS + } + }); + + const mailOptions = { + from: process.env.EMAIL_USER, + to: process.env.ADMIN_EMAIL || process.env.EMAIL_USER, + subject: `New Contact Form Submission: ${contact.subject}`, + html: ` +
Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
+Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
+Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
+Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
+Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
+Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
+Name: ${contact.name}
+Email: ${contact.email}
+Phone: ${contact.phone || 'Not provided'}
+Company: ${contact.company || 'Not provided'}
+Subject: ${contact.subject}
+Message:
+${contact.message.replace(/\n/g, '
')}
Source: ${contact.source}
+Submitted: ${contact.createdAt}
++ <%- __('about.hero.subtitle') %> +
++ <%- __('about.company.description1') %> +
++ <%- __('about.company.description2') %> +
+ + ++ <%- __('about.mission.description') %> +
++ <%- __('about.values.innovation.description') %> +
++ <%- __('about.values.quality.description') %> +
++ <%- __('about.values.partnership.description') %> +
++ <%- __('about.cta.subtitle') %> +
+ + <%- __('about.cta.button') %> + + ++ <%- __('about.hero.subtitle') %> +
++ <%- __('about.company.description1') %> +
++ <%- __('about.company.description2') %> +
+ + ++ <%- __('about.mission.description') %> +
++ <%- __('about.values.innovation.description') %> +
++ <%- __('about.values.quality.description') %> +
++ <%- __('about.values.partnership.description') %> +
++ <%- __('about.cta.subtitle') %> +
+ + <%- __('about.cta.button') %> + + ++ <%- __('about.hero.subtitle') %> +
++ <%- __('about.company.description1') %> +
++ <%- __('about.company.description2') %> +
+ + ++ <%- __('about.mission.description') %> +
++ <%- __('about.values.innovation.description') %> +
++ <%- __('about.values.quality.description') %> +
++ <%- __('about.values.partnership.description') %> +
++ <%- __('about.cta.subtitle') %> +
+ + <%- __('about.cta.button') %> + + ++ <%- __('about.hero.subtitle') %> +
++ <%- __('about.company.description1') %> +
++ <%- __('about.company.description2') %> +
+ + ++ <%- __('about.mission.description') %> +
++ <%- __('about.values.innovation.description') %> +
++ <%- __('about.values.quality.description') %> +
++ <%- __('about.values.partnership.description') %> +
++ <%- __('about.cta.subtitle') %> +
+ + <%- __('about.cta.button') %> + + +Создание и редактирование баннеров для сайта
+Создание и редактирование баннеров для сайта
+Создание и редактирование баннеров для сайта
+Создание и редактирование баннеров для сайта
+Создание и редактирование баннеров для сайта
+Создание и редактирование баннеров для сайта
++ <%= contact.name %> +
+ <% if (contact.serviceInterest) { %> + + <%= contact.serviceInterest %> + + <% } %> ++ <%= contact.email %> +
+ • ++ <%= new Date(contact.createdAt).toLocaleDateString('ru-RU') %> +
++ <%= contact.message.substring(0, 100) %>... +
+Сообщения не найдены
++ <%= contact.name %> +
+ <% if (contact.serviceInterest) { %> + + <%= contact.serviceInterest %> + + <% } %> ++ <%= contact.email %> +
+ • ++ <%= new Date(contact.createdAt).toLocaleDateString('ru-RU') %> +
++ <%= contact.message.substring(0, 100) %>... +
+Сообщения не найдены
+<%= contact.message %>
+<%= contact.message %>
+<%= t('admin.dashboard_subtitle') %>
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +<%= t('admin.dashboard_subtitle') %>
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+<%= t('admin.no_recent_portfolio') %>
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+<%= t('admin.no_recent_contacts') %>
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +Обзор основных показателей сайта
++ <%= project.title %> +
++ <%= project.category %> +
+Нет недавних проектов
+ <% } %> ++ <%= contact.name %> +
++ <%= contact.email %> +
+Нет недавних сообщений
+ <% } %> +<%= message %>
+<%= message %>
+<%= message %>
+<%= message %>
++ <%= t('admin.login_subtitle') %> +
++ <%= t('admin.login_subtitle') %> +
++ Войдите в свой аккаунт для управления сайтом +
++ Войдите в свой аккаунт для управления сайтом +
++ Войдите в свой аккаунт для управления сайтом +
++ Войдите в свой аккаунт для управления сайтом +
++ Войдите в свой аккаунт для управления сайтом +
++ Войдите в свой аккаунт для управления сайтом +
+Управление изображениями и файлами сайта
+Загрузка медиа файлов...
+Управление изображениями и файлами сайта
+Загрузка медиа файлов...
+Заполните информацию о проекте для добавления в портфолио
+