feat(ZEE-29): implement design system, dark mode, and JSON content management
- Add comprehensive design system with CSS variables, animations, and utility classes - Implement dark mode with ThemeProvider (system preference + manual toggle) - Create JSON-based content management system in src/content/ - Update all pages to use structured JSON content - Add ThemeProvider component with theme toggle button - Update Header with glass effect and animated mobile menu - Update Footer with dark mode support - Update documentation (README.md, CLAUDE.md, knowledge.md, proto/README.md) - Sync with Linear (ZEE-29 completed)
This commit is contained in:
+115
-20
@@ -1,36 +1,131 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
# mozdIT Bt. Website - Next.js Application
|
||||
|
||||
## Getting Started
|
||||
Modern Next.js 14 website for mozdIT Bt. - Hungarian IT services company.
|
||||
|
||||
First, run the development server:
|
||||
## 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Development server (with Turbopack)
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
|
||||
# Production build
|
||||
npm run build
|
||||
|
||||
# Run tests
|
||||
npm test
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
Open [http://localhost:3000](http://localhost:3000) to view the site.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
## 📁 Project Structure
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
```
|
||||
src/
|
||||
├── app/ # Next.js App Router
|
||||
│ ├── page.tsx # Homepage
|
||||
│ ├── rolunk/ # About page
|
||||
│ ├── szolgaltatasok/ # Services page
|
||||
│ ├── kapcsolat/ # Contact page
|
||||
│ ├── api/ # API routes
|
||||
│ └── globals.css # Design system & styles
|
||||
├── components/ # React components
|
||||
│ ├── Header.tsx # Navigation header
|
||||
│ ├── Footer.tsx # Site footer
|
||||
│ └── ThemeProvider.tsx # Dark mode provider
|
||||
├── content/ # JSON content management
|
||||
│ ├── types.ts # Content type definitions
|
||||
│ ├── index.ts # Content loader
|
||||
│ ├── common.json # Shared texts
|
||||
│ └── pages/ # Page-specific content
|
||||
├── config/ # Site configuration
|
||||
├── lib/ # Utilities
|
||||
└── types/ # TypeScript definitions
|
||||
```
|
||||
|
||||
## Learn More
|
||||
## 🎨 Design System
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
The project uses a comprehensive design system defined in `globals.css`:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
### CSS Variables
|
||||
- Brand colors (`--color-primary-*`)
|
||||
- Semantic colors (`--color-background`, `--color-foreground`)
|
||||
- Shadows, transitions, border radius
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
### Dark Mode
|
||||
- Automatic system preference detection
|
||||
- Manual toggle via ThemeProvider
|
||||
- Uses `data-theme="dark"` attribute
|
||||
|
||||
## Deploy on Vercel
|
||||
### Animations
|
||||
- `animate-fade-in-up` - Fade in with upward motion
|
||||
- `animate-float` - Floating effect
|
||||
- `animate-pulse-slow` - Slow pulsing
|
||||
- `hover-lift`, `hover-scale`, `hover-glow` - Hover effects
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
### Utility Classes
|
||||
- `.card` - Card component styling
|
||||
- `.btn`, `.btn-primary`, `.btn-secondary` - Button styles
|
||||
- `.icon-container` - Icon wrapper styling
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
## 📝 Content Management
|
||||
|
||||
All page content is managed through JSON files in `src/content/`:
|
||||
|
||||
```typescript
|
||||
import { content, getPageContent } from '@/content'
|
||||
|
||||
// Access specific page content
|
||||
const aboutContent = content.pages.about
|
||||
|
||||
// Or use the helper function
|
||||
const servicesContent = getPageContent('services')
|
||||
```
|
||||
|
||||
### Content Files
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `common.json` | Shared texts (buttons, labels, validation) |
|
||||
| `pages/home.json` | Homepage CTA section |
|
||||
| `pages/about.json` | About page (hero, story, mission, team, CTA) |
|
||||
| `pages/services.json` | Services (hero, details, support, CTA) |
|
||||
| `pages/contact.json` | Contact (form labels, FAQ, info) |
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
```bash
|
||||
# Unit tests
|
||||
npm test
|
||||
|
||||
# Watch mode
|
||||
npm run test:watch
|
||||
|
||||
# Coverage report
|
||||
npm run test:coverage
|
||||
|
||||
# All test suites
|
||||
npm run test:all
|
||||
```
|
||||
|
||||
## 🐳 Docker Development
|
||||
|
||||
For full-stack development with MongoDB and monitoring:
|
||||
|
||||
```bash
|
||||
# From project root
|
||||
docker-compose -f docker-compose.dev.yml up -d
|
||||
```
|
||||
|
||||
Services:
|
||||
- **Website**: http://localhost:3000
|
||||
- **MongoDB UI**: http://localhost:8081
|
||||
- **Grafana**: http://localhost:3001
|
||||
|
||||
## 📚 Learn More
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs)
|
||||
- [Tailwind CSS](https://tailwindcss.com/docs)
|
||||
- [Project Documentation](../README.md)
|
||||
|
||||
+543
-13
@@ -1,26 +1,556 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
/* ========================================
|
||||
mozdIT Bt. Design System
|
||||
======================================== */
|
||||
|
||||
/* Design Tokens - Light Theme */
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
/* Brand Colors */
|
||||
--color-primary-50: #eff6ff;
|
||||
--color-primary-100: #dbeafe;
|
||||
--color-primary-200: #bfdbfe;
|
||||
--color-primary-300: #93c5fd;
|
||||
--color-primary-400: #60a5fa;
|
||||
--color-primary-500: #3b82f6;
|
||||
--color-primary-600: #2563eb;
|
||||
--color-primary-700: #1d4ed8;
|
||||
--color-primary-800: #1e40af;
|
||||
--color-primary-900: #1e3a8a;
|
||||
--color-primary-950: #172554;
|
||||
|
||||
/* Accent Colors */
|
||||
--color-accent-50: #eef2ff;
|
||||
--color-accent-100: #e0e7ff;
|
||||
--color-accent-200: #c7d2fe;
|
||||
--color-accent-500: #6366f1;
|
||||
--color-accent-600: #4f46e5;
|
||||
|
||||
/* Success Colors */
|
||||
--color-success-50: #f0fdf4;
|
||||
--color-success-500: #22c55e;
|
||||
--color-success-600: #16a34a;
|
||||
|
||||
/* Warning Colors */
|
||||
--color-warning-50: #fffbeb;
|
||||
--color-warning-500: #f59e0b;
|
||||
|
||||
/* Error Colors */
|
||||
--color-error-50: #fef2f2;
|
||||
--color-error-500: #ef4444;
|
||||
--color-error-600: #dc2626;
|
||||
|
||||
/* Neutral Colors - Light Mode */
|
||||
--color-background: #ffffff;
|
||||
--color-background-secondary: #f9fafb;
|
||||
--color-background-tertiary: #f3f4f6;
|
||||
--color-foreground: #111827;
|
||||
--color-foreground-secondary: #374151;
|
||||
--color-foreground-muted: #6b7280;
|
||||
--color-border: #e5e7eb;
|
||||
--color-border-light: #f3f4f6;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
|
||||
/* Transitions */
|
||||
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--transition-bounce: 500ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
/* Spacing */
|
||||
--container-padding: 1rem;
|
||||
--section-spacing: 4rem;
|
||||
|
||||
/* Border Radius */
|
||||
--radius-sm: 0.375rem;
|
||||
--radius-md: 0.5rem;
|
||||
--radius-lg: 0.75rem;
|
||||
--radius-xl: 1rem;
|
||||
--radius-full: 9999px;
|
||||
|
||||
/* Fonts */
|
||||
--font-sans: var(--font-geist-sans), system-ui, -apple-system, sans-serif;
|
||||
--font-mono: var(--font-geist-mono), 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
/* Dark Mode */
|
||||
[data-theme="dark"] {
|
||||
--color-background: #0f172a;
|
||||
--color-background-secondary: #1e293b;
|
||||
--color-background-tertiary: #334155;
|
||||
--color-foreground: #f8fafc;
|
||||
--color-foreground-secondary: #e2e8f0;
|
||||
--color-foreground-muted: #94a3b8;
|
||||
--color-border: #334155;
|
||||
--color-border-light: #1e293b;
|
||||
|
||||
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3);
|
||||
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3);
|
||||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3);
|
||||
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.4);
|
||||
}
|
||||
|
||||
/* System preference fallback */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
:root:not([data-theme="light"]) {
|
||||
--color-background: #0f172a;
|
||||
--color-background-secondary: #1e293b;
|
||||
--color-background-tertiary: #334155;
|
||||
--color-foreground: #f8fafc;
|
||||
--color-foreground-secondary: #e2e8f0;
|
||||
--color-foreground-muted: #94a3b8;
|
||||
--color-border: #334155;
|
||||
--color-border-light: #1e293b;
|
||||
|
||||
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3);
|
||||
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3);
|
||||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3);
|
||||
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tailwind Theme Extension */
|
||||
@theme inline {
|
||||
--color-background: var(--color-background);
|
||||
--color-foreground: var(--color-foreground);
|
||||
--font-sans: var(--font-sans);
|
||||
--font-mono: var(--font-mono);
|
||||
}
|
||||
|
||||
/* Base Styles */
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background: var(--color-background);
|
||||
color: var(--color-foreground);
|
||||
font-family: var(--font-sans);
|
||||
transition: background-color var(--transition-normal), color var(--transition-normal);
|
||||
}
|
||||
|
||||
/* Selection */
|
||||
::selection {
|
||||
background: var(--color-primary-500);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Focus Styles */
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--color-primary-500);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Custom Scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--color-background-secondary);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--color-border);
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--color-foreground-muted);
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Utility Classes
|
||||
======================================== */
|
||||
|
||||
/* Gradient Backgrounds */
|
||||
.bg-gradient-hero {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--color-primary-50) 0%,
|
||||
var(--color-accent-50) 50%,
|
||||
var(--color-primary-100) 100%
|
||||
);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .bg-gradient-hero {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--color-background-secondary) 0%,
|
||||
var(--color-background-tertiary) 50%,
|
||||
var(--color-background-secondary) 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Glass Effect */
|
||||
.glass {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .glass {
|
||||
background: rgba(15, 23, 42, 0.8);
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Animation Keyframes
|
||||
======================================== */
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Animation Classes */
|
||||
.animate-fade-in {
|
||||
animation: fadeIn var(--transition-slow) ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-fade-in-up {
|
||||
animation: fadeInUp 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-fade-in-down {
|
||||
animation: fadeInDown 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-slide-in-left {
|
||||
animation: slideInLeft 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-slide-in-right {
|
||||
animation: slideInRight 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-scale-in {
|
||||
animation: scaleIn 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-bounce-slow {
|
||||
animation: bounce 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-pulse-slow {
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-float {
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-spin-slow {
|
||||
animation: spin 3s linear infinite;
|
||||
}
|
||||
|
||||
/* Staggered animations for children */
|
||||
.stagger-children > *:nth-child(1) { animation-delay: 0ms; }
|
||||
.stagger-children > *:nth-child(2) { animation-delay: 100ms; }
|
||||
.stagger-children > *:nth-child(3) { animation-delay: 200ms; }
|
||||
.stagger-children > *:nth-child(4) { animation-delay: 300ms; }
|
||||
.stagger-children > *:nth-child(5) { animation-delay: 400ms; }
|
||||
.stagger-children > *:nth-child(6) { animation-delay: 500ms; }
|
||||
|
||||
/* Hover Animations */
|
||||
.hover-lift {
|
||||
transition: transform var(--transition-normal), box-shadow var(--transition-normal);
|
||||
}
|
||||
|
||||
.hover-lift:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.hover-scale {
|
||||
transition: transform var(--transition-fast);
|
||||
}
|
||||
|
||||
.hover-scale:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.hover-glow {
|
||||
transition: box-shadow var(--transition-normal);
|
||||
}
|
||||
|
||||
.hover-glow:hover {
|
||||
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
|
||||
}
|
||||
|
||||
/* Button Styles */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-weight: 500;
|
||||
border-radius: var(--radius-md);
|
||||
transition: all var(--transition-normal);
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--color-primary-600);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: var(--color-primary-700);
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: transparent;
|
||||
color: var(--color-primary-600);
|
||||
border: 2px solid var(--color-primary-600);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: var(--color-primary-50);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .btn-secondary:hover {
|
||||
background: var(--color-primary-900);
|
||||
}
|
||||
|
||||
/* Card Styles */
|
||||
.card {
|
||||
background: var(--color-background);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: 2rem;
|
||||
transition: all var(--transition-normal);
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--color-primary-200);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card:hover {
|
||||
border-color: var(--color-primary-800);
|
||||
}
|
||||
|
||||
/* Icon Container */
|
||||
.icon-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
background: var(--color-primary-100);
|
||||
border-radius: var(--radius-lg);
|
||||
transition: all var(--transition-normal);
|
||||
}
|
||||
|
||||
.icon-container-lg {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .icon-container {
|
||||
background: var(--color-primary-900);
|
||||
}
|
||||
|
||||
.group:hover .icon-container {
|
||||
background: var(--color-primary-200);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .group:hover .icon-container {
|
||||
background: var(--color-primary-800);
|
||||
}
|
||||
|
||||
/* Section Styles */
|
||||
.section {
|
||||
padding: var(--section-spacing) 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 80rem;
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--container-padding);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--container-padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
:root {
|
||||
--container-padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Link Styles */
|
||||
.link {
|
||||
color: var(--color-primary-600);
|
||||
text-decoration: none;
|
||||
transition: color var(--transition-fast);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: var(--color-primary-700);
|
||||
}
|
||||
|
||||
.link-underline::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--color-primary-600);
|
||||
transition: width var(--transition-normal);
|
||||
}
|
||||
|
||||
.link-underline:hover::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Prose adjustments for dark mode */
|
||||
[data-theme="dark"] .prose {
|
||||
--tw-prose-body: var(--color-foreground-secondary);
|
||||
--tw-prose-headings: var(--color-foreground);
|
||||
--tw-prose-links: var(--color-primary-400);
|
||||
--tw-prose-bold: var(--color-foreground);
|
||||
}
|
||||
|
||||
/* Reduce motion for accessibility */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { siteConfig } from '@/config/site'
|
||||
import { content } from '@/content'
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
const { contact: pageContent } = content.pages
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: `Kapcsolat | ${siteConfig.general.name}`,
|
||||
description: 'Vegye fel velünk a kapcsolatot! Segítünk minden IT kérdésében. Email, telefon és online űrlap is rendelkezésére áll.',
|
||||
title: `${pageContent.meta.title} | ${siteConfig.general.name}`,
|
||||
description: pageContent.meta.description,
|
||||
openGraph: {
|
||||
title: `Kapcsolat | ${siteConfig.general.name}`,
|
||||
description: 'Vegye fel velünk a kapcsolatot! Segítünk minden IT kérdésében.',
|
||||
title: `${pageContent.meta.title} | ${siteConfig.general.name}`,
|
||||
description: pageContent.meta.description,
|
||||
url: `${siteConfig.general.url}/kapcsolat`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import { siteConfig } from '@/config/site'
|
||||
import { content } from '@/content'
|
||||
import { useState } from 'react'
|
||||
|
||||
const { contact: pageContent } = content.pages
|
||||
|
||||
export default function ContactPage() {
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
@@ -20,27 +23,27 @@ export default function ContactPage() {
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.name.trim()) {
|
||||
newErrors.name = 'A név megadása kötelező'
|
||||
newErrors.name = pageContent.form.fields.name.error
|
||||
}
|
||||
|
||||
if (!formData.email.trim()) {
|
||||
newErrors.email = 'Az email cím megadása kötelező'
|
||||
newErrors.email = pageContent.form.fields.email.errorRequired
|
||||
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
||||
newErrors.email = 'Érvénytelen email cím formátum'
|
||||
newErrors.email = pageContent.form.fields.email.errorInvalid
|
||||
}
|
||||
|
||||
if (!formData.subject.trim()) {
|
||||
newErrors.subject = 'A tárgy megadása kötelező'
|
||||
newErrors.subject = pageContent.form.fields.subject.error
|
||||
}
|
||||
|
||||
if (!formData.message.trim()) {
|
||||
newErrors.message = 'Az üzenet megadása kötelező'
|
||||
newErrors.message = pageContent.form.fields.message.errorRequired
|
||||
} else if (formData.message.trim().length < 10) {
|
||||
newErrors.message = 'Az üzenet legalább 10 karakter hosszú legyen'
|
||||
newErrors.message = pageContent.form.fields.message.errorMinLength
|
||||
}
|
||||
|
||||
if (!formData.gdprConsent) {
|
||||
newErrors.gdprConsent = 'Az adatkezelési tájékoztató elfogadása kötelező'
|
||||
newErrors.gdprConsent = pageContent.form.fields.gdpr.error
|
||||
}
|
||||
|
||||
setErrors(newErrors)
|
||||
@@ -93,7 +96,6 @@ export default function ContactPage() {
|
||||
[name]: type === 'checkbox' ? (e.target as HTMLInputElement).checked : value
|
||||
}))
|
||||
|
||||
// Clear error when user starts typing
|
||||
if (errors[name]) {
|
||||
setErrors(prev => ({ ...prev, [name]: '' }))
|
||||
}
|
||||
@@ -105,10 +107,10 @@ export default function ContactPage() {
|
||||
<section className="bg-gradient-to-r from-blue-50 to-indigo-50 py-16">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
|
||||
Kapcsolat
|
||||
{pageContent.hero.title}
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 leading-relaxed">
|
||||
Vegye fel velünk a kapcsolatot! Szívesen segítünk minden IT kérdésében.
|
||||
{pageContent.hero.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -119,13 +121,13 @@ export default function ContactPage() {
|
||||
<div>
|
||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-6">
|
||||
Küldjön üzenetet
|
||||
{pageContent.form.title}
|
||||
</h2>
|
||||
|
||||
{submitStatus === 'success' && (
|
||||
<div className="mb-6 p-4 bg-green-50 border border-green-200 rounded-md">
|
||||
<p className="text-green-800">
|
||||
✅ Köszönjük üzenetét! Hamarosan felvesszük Önnel a kapcsolatot.
|
||||
✅ {pageContent.form.successMessage}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -133,7 +135,7 @@ export default function ContactPage() {
|
||||
{submitStatus === 'error' && (
|
||||
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-md">
|
||||
<p className="text-red-800">
|
||||
❌ Hiba történt az üzenet küldése során. Kérjük, próbálja újra vagy írjon közvetlenül a {siteConfig.contact.email} címre.
|
||||
❌ {pageContent.form.errorMessage.replace('{email}', siteConfig.contact.email)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -141,7 +143,7 @@ export default function ContactPage() {
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Név *
|
||||
{pageContent.form.fields.name.label} *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -152,14 +154,14 @@ export default function ContactPage() {
|
||||
className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||
errors.name ? 'border-red-300' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Az Ön neve"
|
||||
placeholder={pageContent.form.fields.name.placeholder}
|
||||
/>
|
||||
{errors.name && <p className="mt-1 text-sm text-red-600">{errors.name}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Email cím *
|
||||
{pageContent.form.fields.email.label} *
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
@@ -170,14 +172,14 @@ export default function ContactPage() {
|
||||
className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||
errors.email ? 'border-red-300' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="pelda@email.hu"
|
||||
placeholder={pageContent.form.fields.email.placeholder}
|
||||
/>
|
||||
{errors.email && <p className="mt-1 text-sm text-red-600">{errors.email}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="subject" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Tárgy *
|
||||
{pageContent.form.fields.subject.label} *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -188,14 +190,14 @@ export default function ContactPage() {
|
||||
className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||
errors.subject ? 'border-red-300' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Miben segíthetünk?"
|
||||
placeholder={pageContent.form.fields.subject.placeholder}
|
||||
/>
|
||||
{errors.subject && <p className="mt-1 text-sm text-red-600">{errors.subject}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="message" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Üzenet *
|
||||
{pageContent.form.fields.message.label} *
|
||||
</label>
|
||||
<textarea
|
||||
id="message"
|
||||
@@ -206,7 +208,7 @@ export default function ContactPage() {
|
||||
className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||
errors.message ? 'border-red-300' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Írja le részletesen kérését vagy kérdését..."
|
||||
placeholder={pageContent.form.fields.message.placeholder}
|
||||
/>
|
||||
{errors.message && <p className="mt-1 text-sm text-red-600">{errors.message}</p>}
|
||||
</div>
|
||||
@@ -220,9 +222,10 @@ export default function ContactPage() {
|
||||
onChange={handleInputChange}
|
||||
className="mt-1 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
|
||||
/>
|
||||
<span className="text-sm text-gray-700">
|
||||
Elfogadom az <a href="/adatkezelesi-tajekoztato" className="text-blue-600 hover:text-blue-700 underline">adatkezelési tájékoztatót</a> és hozzájárulok személyes adataim kezeléséhez a kapcsolatfelvétel céljából. *
|
||||
</span>
|
||||
<span
|
||||
className="text-sm text-gray-700"
|
||||
dangerouslySetInnerHTML={{ __html: pageContent.form.fields.gdpr.label + ' *' }}
|
||||
/>
|
||||
</label>
|
||||
{errors.gdprConsent && <p className="mt-1 text-sm text-red-600">{errors.gdprConsent}</p>}
|
||||
</div>
|
||||
@@ -232,7 +235,7 @@ export default function ContactPage() {
|
||||
disabled={isSubmitting}
|
||||
className="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-3 px-4 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
||||
>
|
||||
{isSubmitting ? 'Küldés...' : 'Üzenet küldése'}
|
||||
{isSubmitting ? pageContent.form.submittingButton : pageContent.form.submitButton}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -242,7 +245,7 @@ export default function ContactPage() {
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-6">
|
||||
Elérhetőségek
|
||||
{pageContent.info.title}
|
||||
</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
@@ -251,7 +254,7 @@ export default function ContactPage() {
|
||||
<span className="text-lg">✉️</span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-1">Email</h3>
|
||||
<h3 className="font-semibold text-gray-900 mb-1">{pageContent.info.email.title}</h3>
|
||||
<a
|
||||
href={`mailto:${siteConfig.contact.email}`}
|
||||
className="text-blue-600 hover:text-blue-700"
|
||||
@@ -259,7 +262,7 @@ export default function ContactPage() {
|
||||
{siteConfig.contact.email}
|
||||
</a>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
24 órán belül válaszolunk
|
||||
{pageContent.info.email.responseTime}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -269,7 +272,7 @@ export default function ContactPage() {
|
||||
<span className="text-lg">🏢</span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-1">Cég</h3>
|
||||
<h3 className="font-semibold text-gray-900 mb-1">{pageContent.info.company.title}</h3>
|
||||
<p className="text-gray-700">{siteConfig.general.name}</p>
|
||||
<p className="text-sm text-gray-600">{siteConfig.contact.address}</p>
|
||||
</div>
|
||||
@@ -280,17 +283,17 @@ export default function ContactPage() {
|
||||
<span className="text-lg">🌐</span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-1">Webmail hozzáférés</h3>
|
||||
<h3 className="font-semibold text-gray-900 mb-1">{pageContent.info.webmail.title}</h3>
|
||||
<a
|
||||
href={siteConfig.hero.cta.primary.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-600 hover:text-blue-700"
|
||||
>
|
||||
Webmail belépés →
|
||||
{pageContent.info.webmail.linkText}
|
||||
</a>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Ügyfeleink számára
|
||||
{pageContent.info.webmail.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -300,30 +303,16 @@ export default function ContactPage() {
|
||||
{/* FAQ */}
|
||||
<div className="bg-gray-50 rounded-xl p-8">
|
||||
<h2 className="text-xl font-bold text-gray-900 mb-6">
|
||||
Gyakori kérdések
|
||||
{pageContent.faq.title}
|
||||
</h2>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">Milyen gyorsan válaszolnak?</h3>
|
||||
<p className="text-gray-600 text-sm">
|
||||
Email üzenetekre 24 órán belül, sürgős esetekben telefonon is elérhetők vagyunk.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">Van ingyenes konzultáció?</h3>
|
||||
<p className="text-gray-600 text-sm">
|
||||
Igen! Az első konzultáció mindig ingyenes, hogy megismerjük az Ön igényeit.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">Milyen fizetési módokat fogadnak el?</h3>
|
||||
<p className="text-gray-600 text-sm">
|
||||
Banki átutalás, PayPal és kártyás fizetés is lehetséges.
|
||||
</p>
|
||||
</div>
|
||||
{pageContent.faq.items.map((item, index) => (
|
||||
<div key={index}>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">{item.question}</h3>
|
||||
<p className="text-gray-600 text-sm">{item.answer}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import Header from "../components/Header";
|
||||
import Footer from "../components/Footer";
|
||||
import { ThemeProvider } from "../components/ThemeProvider";
|
||||
import { siteConfig } from "../config/site";
|
||||
|
||||
const geistSans = Geist({
|
||||
@@ -61,15 +62,34 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="hu">
|
||||
<html lang="hu" suppressHydrationWarning>
|
||||
<head>
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function() {
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'dark') {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
} else if (savedTheme === 'light') {
|
||||
document.documentElement.setAttribute('data-theme', 'light');
|
||||
}
|
||||
})();
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased min-h-screen flex flex-col`}
|
||||
style={{ background: 'var(--color-background)', color: 'var(--color-foreground)' }}
|
||||
>
|
||||
<Header />
|
||||
<main className="flex-1">
|
||||
{children}
|
||||
</main>
|
||||
<Footer />
|
||||
<ThemeProvider>
|
||||
<Header />
|
||||
<main className="flex-1">
|
||||
{children}
|
||||
</main>
|
||||
<Footer />
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
+198
-66
@@ -1,25 +1,54 @@
|
||||
import { siteConfig } from '@/config/site'
|
||||
import { content } from '@/content'
|
||||
|
||||
const { home: pageContent } = content.pages
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="space-y-16">
|
||||
<div className="space-y-0">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-r from-blue-50 to-indigo-50 py-20">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 mb-6 leading-tight">
|
||||
<section className="bg-gradient-hero py-20 lg:py-28 relative overflow-hidden">
|
||||
{/* Background decoration */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<div
|
||||
className="absolute -top-40 -right-40 w-80 h-80 rounded-full opacity-30 animate-pulse-slow"
|
||||
style={{ background: 'var(--color-primary-200)' }}
|
||||
/>
|
||||
<div
|
||||
className="absolute -bottom-40 -left-40 w-96 h-96 rounded-full opacity-20 animate-pulse-slow"
|
||||
style={{ background: 'var(--color-accent-200)', animationDelay: '1s' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<h1
|
||||
className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 leading-tight animate-fade-in-up"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{siteConfig.hero.title}
|
||||
</h1>
|
||||
<p className="text-lg md:text-xl text-gray-600 max-w-4xl mx-auto mb-8 leading-relaxed">
|
||||
<p
|
||||
className="text-lg md:text-xl max-w-4xl mx-auto mb-10 leading-relaxed animate-fade-in-up"
|
||||
style={{ color: 'var(--color-foreground-muted)', animationDelay: '100ms' }}
|
||||
>
|
||||
{siteConfig.hero.description}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<div
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center items-center animate-fade-in-up"
|
||||
style={{ animationDelay: '200ms' }}
|
||||
>
|
||||
<a
|
||||
href={siteConfig.hero.cta.primary.href}
|
||||
target={siteConfig.hero.cta.primary.external ? '_blank' : undefined}
|
||||
rel={siteConfig.hero.cta.primary.external ? 'noopener noreferrer' : undefined}
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white font-medium px-8 py-4 rounded-md transition-colors text-lg inline-flex items-center gap-2"
|
||||
className="btn btn-primary text-lg px-8 py-4 group"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg
|
||||
className="w-5 h-5 transition-transform duration-200 group-hover:scale-110"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10" />
|
||||
</svg>
|
||||
{siteConfig.hero.cta.primary.text}
|
||||
@@ -27,7 +56,7 @@ export default function Home() {
|
||||
{siteConfig.hero.cta.secondary && (
|
||||
<a
|
||||
href={siteConfig.hero.cta.secondary.href}
|
||||
className="border-2 border-blue-600 text-blue-600 hover:bg-blue-50 font-medium px-8 py-4 rounded-md transition-colors text-lg"
|
||||
className="btn btn-secondary text-lg px-8 py-4"
|
||||
>
|
||||
{siteConfig.hero.cta.secondary.text}
|
||||
</a>
|
||||
@@ -37,19 +66,44 @@ export default function Home() {
|
||||
</section>
|
||||
|
||||
{/* USP Section */}
|
||||
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 bg-gray-50">
|
||||
<div className="text-center">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-8">
|
||||
{siteConfig.about.title}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
|
||||
{siteConfig.about.usps.map((usp) => (
|
||||
<div key={usp.id} className="text-center">
|
||||
<div className="w-16 h-16 bg-blue-100 group-hover:bg-blue-200 rounded-full flex items-center justify-center mx-auto mb-4 transition-colors">
|
||||
<section
|
||||
className="py-20"
|
||||
style={{ background: 'var(--color-background-secondary)' }}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-bold mb-4"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{siteConfig.about.title}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 stagger-children">
|
||||
{siteConfig.about.usps.map((usp, index) => (
|
||||
<div
|
||||
key={usp.id}
|
||||
className="group text-center p-6 rounded-xl transition-all duration-300 hover-lift animate-fade-in-up"
|
||||
style={{
|
||||
background: 'var(--color-background)',
|
||||
border: '1px solid var(--color-border)',
|
||||
animationDelay: `${index * 100}ms`
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="icon-container icon-container-lg mx-auto mb-4"
|
||||
>
|
||||
<span className="text-2xl">{usp.icon}</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-2">{usp.title}</h3>
|
||||
<p className="text-gray-600">{usp.description}</p>
|
||||
<h3
|
||||
className="text-lg font-semibold mb-2 transition-colors duration-200"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{usp.title}
|
||||
</h3>
|
||||
<p style={{ color: 'var(--color-foreground-muted)' }}>
|
||||
{usp.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -57,64 +111,142 @@ export default function Home() {
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
{siteConfig.services.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 max-w-3xl mx-auto">
|
||||
{siteConfig.services.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
||||
{siteConfig.services.services.map((service) => (
|
||||
<div key={service.id} className="group bg-white p-8 rounded-xl shadow-sm border border-gray-200 hover:shadow-md transition-all duration-300 hover:border-blue-200">
|
||||
<div className="w-12 h-12 bg-blue-100 group-hover:bg-blue-200 rounded-lg flex items-center justify-center mb-4 transition-colors">
|
||||
<span className="text-xl">{service.icon}</span>
|
||||
<section
|
||||
className="py-20"
|
||||
style={{ background: 'var(--color-background)' }}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-bold mb-4"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{siteConfig.services.title}
|
||||
</h2>
|
||||
<p
|
||||
className="text-lg max-w-3xl mx-auto"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{siteConfig.services.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
||||
{siteConfig.services.services.map((service, index) => (
|
||||
<div
|
||||
key={service.id}
|
||||
className="group card hover-lift"
|
||||
style={{ animationDelay: `${index * 100}ms` }}
|
||||
>
|
||||
<div className="icon-container mb-4">
|
||||
<span className="text-xl">{service.icon}</span>
|
||||
</div>
|
||||
<h3
|
||||
className="text-xl font-semibold mb-3 transition-colors duration-200 group-hover:text-blue-600"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{service.title}
|
||||
</h3>
|
||||
<p
|
||||
className="leading-relaxed mb-4"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{service.description}
|
||||
</p>
|
||||
<div className="mb-4">
|
||||
<h4
|
||||
className="text-sm font-semibold mb-2"
|
||||
style={{ color: 'var(--color-foreground-secondary)' }}
|
||||
>
|
||||
{pageContent.serviceFeatures.title}
|
||||
</h4>
|
||||
<ul
|
||||
className="text-sm space-y-1.5"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{service.features.map((feature, idx) => (
|
||||
<li key={idx} className="flex items-start group/item">
|
||||
<span
|
||||
className="mr-2 transition-transform duration-200 group-hover/item:scale-125"
|
||||
style={{ color: 'var(--color-success-500)' }}
|
||||
>
|
||||
✓
|
||||
</span>
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<a
|
||||
href="/kapcsolat"
|
||||
className="inline-flex items-center font-medium transition-all duration-200 group/link"
|
||||
style={{ color: 'var(--color-primary-600)' }}
|
||||
>
|
||||
{service.ctaText}
|
||||
<svg
|
||||
className="w-4 h-4 ml-1 transition-transform duration-200 group-hover/link:translate-x-1"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 mb-3 group-hover:text-blue-600 transition-colors">{service.title}</h3>
|
||||
<p className="text-gray-600 leading-relaxed">
|
||||
{service.description}
|
||||
</p>
|
||||
<div className="mt-4">
|
||||
<h4 className="text-sm font-semibold text-gray-700 mb-2">Szolgáltatás jellemzők:</h4>
|
||||
<ul className="text-sm text-gray-600 space-y-1">
|
||||
{service.features.map((feature, index) => (
|
||||
<li key={index} className="flex items-start">
|
||||
<span className="text-blue-500 mr-2">✓</span>
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<a href="/kapcsolat" className="inline-flex items-center text-blue-600 hover:text-blue-700 font-medium mt-4 transition-colors">
|
||||
{service.ctaText}
|
||||
<svg className="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="bg-gray-900 text-white py-16">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl font-bold mb-4">
|
||||
Kapcsolatfelvétel az első lépés
|
||||
<section
|
||||
className="py-20 relative overflow-hidden"
|
||||
style={{ background: 'var(--color-foreground)' }}
|
||||
>
|
||||
{/* Animated background elements */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none opacity-10">
|
||||
<div
|
||||
className="absolute top-10 left-10 w-32 h-32 rounded-full animate-float"
|
||||
style={{ background: 'var(--color-primary-500)' }}
|
||||
/>
|
||||
<div
|
||||
className="absolute bottom-10 right-20 w-24 h-24 rounded-full animate-float"
|
||||
style={{ background: 'var(--color-accent-500)', animationDelay: '0.5s' }}
|
||||
/>
|
||||
<div
|
||||
className="absolute top-1/2 right-1/4 w-16 h-16 rounded-full animate-float"
|
||||
style={{ background: 'var(--color-primary-400)', animationDelay: '1s' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-bold mb-4"
|
||||
style={{ color: 'var(--color-background)' }}
|
||||
>
|
||||
{pageContent.cta.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-300 mb-8">
|
||||
Mutassuk meg, hogyan segíthetünk Önnek megvalósítani címeit!
|
||||
<p
|
||||
className="text-xl mb-8 max-w-2xl mx-auto"
|
||||
style={{ color: 'var(--color-background)', opacity: 0.8 }}
|
||||
>
|
||||
{pageContent.cta.subtitle}
|
||||
</p>
|
||||
<a
|
||||
href="/kapcsolat"
|
||||
className="inline-block bg-blue-600 hover:bg-blue-700 text-white font-medium px-8 py-3 rounded-md transition-colors"
|
||||
className="btn btn-primary text-lg px-8 py-4 hover-glow"
|
||||
>
|
||||
Kapcsolatfelvétel
|
||||
{pageContent.cta.button}
|
||||
<svg
|
||||
className="w-5 h-5 ml-2"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
+141
-103
@@ -1,153 +1,191 @@
|
||||
import { siteConfig } from '@/config/site'
|
||||
import { content } from '@/content'
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
const { about: pageContent } = content.pages
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: `Rólunk | ${siteConfig.general.name}`,
|
||||
description: 'Ismerje meg a mozdIT Bt. történetét, küldetését és értékeit. Több mint 10 éve nyújtunk megbízható IT szolgáltatásokat.',
|
||||
title: `${pageContent.meta.title} | ${siteConfig.general.name}`,
|
||||
description: pageContent.meta.description,
|
||||
openGraph: {
|
||||
title: `Rólunk | ${siteConfig.general.name}`,
|
||||
description: 'Ismerje meg a mozdIT Bt. történetét, küldetését és értékeit.',
|
||||
title: `${pageContent.meta.title} | ${siteConfig.general.name}`,
|
||||
description: pageContent.meta.ogDescription,
|
||||
url: `${siteConfig.general.url}/rolunk`,
|
||||
},
|
||||
}
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<div className="space-y-16 py-8">
|
||||
<div className="space-y-0">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-r from-blue-50 to-indigo-50 py-16">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
|
||||
Rólunk
|
||||
<section className="bg-gradient-hero py-16 lg:py-24 relative overflow-hidden">
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<div
|
||||
className="absolute -top-20 -right-20 w-60 h-60 rounded-full opacity-20 animate-pulse-slow"
|
||||
style={{ background: 'var(--color-primary-300)' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<h1
|
||||
className="text-4xl md:text-5xl font-bold mb-6 animate-fade-in-up"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{pageContent.hero.title}
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 leading-relaxed">
|
||||
Több mint 10 éve biztosítunk megbízható IT infrastruktúrát és személyes ügyfélszolgálatot
|
||||
<p
|
||||
className="text-xl leading-relaxed animate-fade-in-up"
|
||||
style={{ color: 'var(--color-foreground-muted)', animationDelay: '100ms' }}
|
||||
>
|
||||
{pageContent.hero.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Story Section */}
|
||||
<section className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="prose prose-lg mx-auto">
|
||||
<h2 className="text-3xl font-bold text-gray-900 mb-6">Történetünk</h2>
|
||||
|
||||
<div className="space-y-6 text-gray-700 leading-relaxed">
|
||||
<p>
|
||||
A <strong>mozdIT Bt.</strong> 2010-ben alakult azzal a céllal, hogy kisvállalkozások és
|
||||
magánszemélyek számára nyújtson megbízható, személyes IT szolgáltatásokat.
|
||||
Alapítóink több évtizedes tapasztalattal rendelkeznek a rendszeradminisztráció
|
||||
és webfejlesztés területén.
|
||||
</p>
|
||||
<section
|
||||
className="py-16"
|
||||
style={{ background: 'var(--color-background)' }}
|
||||
>
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="prose prose-lg mx-auto">
|
||||
<h2
|
||||
className="text-3xl font-bold mb-6"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{pageContent.story.title}
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Kezdetben néhány ügyfél weboldalának üzemeltetésével indultunk, ma pedig
|
||||
több száz domain és email fiók működését biztosítjuk. Növekedésünk során
|
||||
mindig szem előtt tartottuk az alapelveinket: <em>megbízhatóság, személyes
|
||||
kapcsolat és műszaki kiválóság</em>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Csapatunk folyamatosan képezi magát a legújabb technológiák terén, hogy
|
||||
ügyfeleink mindig korszerű és biztonságos megoldásokat kapjanak. Büszkék
|
||||
vagyunk arra, hogy sok ügyfelünkkel évek óta tartjuk a kapcsolatot, és
|
||||
számos projektet vittünk sikerre közösen.
|
||||
</p>
|
||||
<div
|
||||
className="space-y-6 leading-relaxed"
|
||||
style={{ color: 'var(--color-foreground-secondary)' }}
|
||||
>
|
||||
{pageContent.story.paragraphs.map((paragraph, index) => (
|
||||
<p
|
||||
key={index}
|
||||
dangerouslySetInnerHTML={{ __html: paragraph }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Mission & Values */}
|
||||
<section className="bg-gray-50 py-16">
|
||||
<section
|
||||
className="py-16"
|
||||
style={{ background: 'var(--color-background-secondary)' }}
|
||||
>
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
||||
Küldetésünk és értékeink
|
||||
<h2
|
||||
className="text-3xl font-bold mb-4"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{pageContent.mission.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 max-w-3xl mx-auto">
|
||||
Minden nap azért dolgozunk, hogy ügyfeleink digitális jelenléte biztonságos,
|
||||
stabil és hatékony legyen.
|
||||
<p
|
||||
className="text-lg max-w-3xl mx-auto"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{pageContent.mission.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<span className="text-2xl">🛡️</span>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 stagger-children">
|
||||
{pageContent.mission.values.map((item, index) => (
|
||||
<div
|
||||
key={item.title}
|
||||
className="group text-center p-8 rounded-xl hover-lift animate-fade-in-up"
|
||||
style={{
|
||||
background: 'var(--color-background)',
|
||||
border: '1px solid var(--color-border)',
|
||||
animationDelay: `${index * 100}ms`
|
||||
}}
|
||||
>
|
||||
<div className="icon-container icon-container-lg mx-auto mb-4">
|
||||
<span className="text-2xl">{item.icon}</span>
|
||||
</div>
|
||||
<h3
|
||||
className="text-xl font-semibold mb-3"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{item.title}
|
||||
</h3>
|
||||
<p style={{ color: 'var(--color-foreground-muted)' }}>
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 mb-3">Megbízhatóság</h3>
|
||||
<p className="text-gray-600">
|
||||
99.9% uptime és 24/7 monitoring biztosítja, hogy szolgáltatásaink mindig
|
||||
elérhetők legyenek.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<span className="text-2xl">👥</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 mb-3">Személyes kapcsolat</h3>
|
||||
<p className="text-gray-600">
|
||||
Minden ügyfél számít számunkra. Személyre szabott megoldásokat kínálunk
|
||||
és mindig elérhetők vagyunk.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<span className="text-2xl">⚡</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 mb-3">Műszaki kiválóság</h3>
|
||||
<p className="text-gray-600">
|
||||
Korszerű technológiák és bevált gyakorlatok alkalmazásával biztosítjuk
|
||||
a legmagasabb színvonalú szolgáltatást.
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Team Section */}
|
||||
<section className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
||||
Szakértő csapat
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600">
|
||||
Tapasztalt IT szakemberek, akik szenvedélyesen dolgoznak az ügyfeleink sikeréért
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
|
||||
<div className="prose prose-lg mx-auto">
|
||||
<p className="text-gray-700 leading-relaxed">
|
||||
Csapatunk rendszeradminisztrátorokból, webfejlesztőkből és ügyfélszolgálati
|
||||
szakértőkből áll. Mindannyian több mint 10 éves tapasztalattal rendelkeznek
|
||||
a maguk területén, és folyamatosan követik a technológiai újdonságokat.
|
||||
</p>
|
||||
|
||||
<p className="text-gray-700 leading-relaxed">
|
||||
Hiszünk abban, hogy a jó kommunikáció és a műszaki tudás együtt teremti meg
|
||||
a tökéletes ügyfélélményt. Ezért minden munkatársunk nemcsak technikai
|
||||
szakértő, hanem kiváló kommunikátor is.
|
||||
<section
|
||||
className="py-16"
|
||||
style={{ background: 'var(--color-background)' }}
|
||||
>
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2
|
||||
className="text-3xl font-bold mb-4"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
{pageContent.team.title}
|
||||
</h2>
|
||||
<p
|
||||
className="text-lg"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{pageContent.team.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<div className="prose prose-lg mx-auto">
|
||||
{pageContent.team.paragraphs.map((paragraph, index) => (
|
||||
<p
|
||||
key={index}
|
||||
className="leading-relaxed"
|
||||
style={{ color: 'var(--color-foreground-secondary)' }}
|
||||
>
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="bg-gray-900 text-white py-16">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl font-bold mb-4">
|
||||
Legyen Ön is elégedett ügyfelünk!
|
||||
<section
|
||||
className="py-16 relative overflow-hidden"
|
||||
style={{ background: 'var(--color-foreground)' }}
|
||||
>
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none opacity-10">
|
||||
<div
|
||||
className="absolute top-10 right-20 w-24 h-24 rounded-full animate-float"
|
||||
style={{ background: 'var(--color-primary-500)' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<h2
|
||||
className="text-3xl font-bold mb-4"
|
||||
style={{ color: 'var(--color-background)' }}
|
||||
>
|
||||
{pageContent.cta.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-300 mb-8">
|
||||
Vegye fel velünk a kapcsolatot, és beszéljük meg, hogyan segíthetünk Önnek.
|
||||
<p
|
||||
className="text-xl mb-8"
|
||||
style={{ color: 'var(--color-background)', opacity: 0.8 }}
|
||||
>
|
||||
{pageContent.cta.subtitle}
|
||||
</p>
|
||||
<a
|
||||
href="/kapcsolat"
|
||||
className="inline-block bg-blue-600 hover:bg-blue-700 text-white font-medium px-8 py-3 rounded-md transition-colors"
|
||||
className="btn btn-primary text-lg px-8 py-4 hover-glow"
|
||||
>
|
||||
Kapcsolatfelvétel
|
||||
{pageContent.cta.button}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { siteConfig } from '@/config/site'
|
||||
import { content } from '@/content'
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
const { services: pageContent } = content.pages
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: `Szolgáltatások | ${siteConfig.general.name}`,
|
||||
description: 'Webhosting, email szolgáltatás és DNS adminisztráció professzionális szinten. Ismerje meg részletes szolgáltatásainkat.',
|
||||
title: `${pageContent.meta.title} | ${siteConfig.general.name}`,
|
||||
description: pageContent.meta.description,
|
||||
openGraph: {
|
||||
title: `Szolgáltatások | ${siteConfig.general.name}`,
|
||||
description: 'Webhosting, email szolgáltatás és DNS adminisztráció professzionális szinten.',
|
||||
title: `${pageContent.meta.title} | ${siteConfig.general.name}`,
|
||||
description: pageContent.meta.ogDescription,
|
||||
url: `${siteConfig.general.url}/szolgaltatasok`,
|
||||
},
|
||||
}
|
||||
@@ -18,10 +21,10 @@ export default function ServicesPage() {
|
||||
<section className="bg-gradient-to-r from-blue-50 to-indigo-50 py-16">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
|
||||
Szolgáltatásaink
|
||||
{pageContent.hero.title}
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 leading-relaxed">
|
||||
Teljes körű IT megoldások kisvállalkozások és magánszemélyek számára
|
||||
{pageContent.hero.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -39,7 +42,7 @@ export default function ServicesPage() {
|
||||
<p className="text-gray-600 leading-relaxed mb-6">{service.description}</p>
|
||||
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-3">Szolgáltatás jellemzők:</h3>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-3">{content.common.labels.features}</h3>
|
||||
<ul className="space-y-2">
|
||||
{service.features.map((feature, index) => (
|
||||
<li key={index} className="flex items-start">
|
||||
@@ -69,97 +72,35 @@ export default function ServicesPage() {
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
||||
Részletes szolgáltatásleírás
|
||||
{pageContent.details.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600">
|
||||
Minden szolgáltatásunk mögött évtizedes tapasztalat és modern technológia áll
|
||||
{pageContent.details.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-12">
|
||||
{/* Web Hosting Details */}
|
||||
<div className="bg-white rounded-xl p-8 shadow-sm">
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-xl">🌐</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4">Web Hosting részletesen</h3>
|
||||
<div className="prose prose-lg text-gray-700">
|
||||
<p>
|
||||
Weboldalak biztonságos és gyors üzemeltetése SSD tárolással, automatikus biztonsági mentéssel
|
||||
és 24/7 monitoringgal. Támogatjuk a PHP, Python, Node.js technológiákat és MySQL/PostgreSQL
|
||||
adatbázisokat.
|
||||
</p>
|
||||
<h4 className="text-lg font-semibold text-gray-900 mt-6 mb-3">Technikai specifikációk:</h4>
|
||||
<ul className="space-y-1">
|
||||
<li>SSD tárhely 10GB-tól 500GB-ig</li>
|
||||
<li>Havi adatforgalom: korlátlan</li>
|
||||
<li>SSL tanúsítványok (Let's Encrypt vagy prémium)</li>
|
||||
<li>CDN integráció a gyorsabb betöltésért</li>
|
||||
<li>Automatikus napi biztonsági mentés</li>
|
||||
<li>cPanel vagy egyedi admin felület</li>
|
||||
</ul>
|
||||
{pageContent.details.services.map((service) => (
|
||||
<div key={service.title} className="bg-white rounded-xl p-8 shadow-sm">
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-xl">{service.icon}</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4">{service.title}</h3>
|
||||
<div className="prose prose-lg text-gray-700">
|
||||
<p>{service.description}</p>
|
||||
<h4 className="text-lg font-semibold text-gray-900 mt-6 mb-3">{service.specs.title}</h4>
|
||||
<ul className="space-y-1">
|
||||
{service.specs.items.map((item, index) => (
|
||||
<li key={index}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Email Service Details */}
|
||||
<div className="bg-white rounded-xl p-8 shadow-sm">
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-xl">✉️</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4">Email szolgáltatás részletesen</h3>
|
||||
<div className="prose prose-lg text-gray-700">
|
||||
<p>
|
||||
Professzionális email fiókok saját domain névvel, spam szűréssel és vírusvédelemmel.
|
||||
Webmail felület és IMAP/POP3/SMTP támogatás minden népszerű email klienssel.
|
||||
</p>
|
||||
<h4 className="text-lg font-semibold text-gray-900 mt-6 mb-3">Email funkciók:</h4>
|
||||
<ul className="space-y-1">
|
||||
<li>Korlátlan email fiókok létrehozása</li>
|
||||
<li>5GB-50GB tárhelyet fiókként</li>
|
||||
<li>Webmail hozzáférés (Roundcube/SOGo)</li>
|
||||
<li>Mobilalkalmazás szinkronizáció</li>
|
||||
<li>Spam és vírusszűrés</li>
|
||||
<li>Email továbbítás és automatikus válaszok</li>
|
||||
<li>Backup és archiválás</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* DNS Administration Details */}
|
||||
<div className="bg-white rounded-xl p-8 shadow-sm">
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-xl">⚙️</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4">DNS adminisztráció részletesen</h3>
|
||||
<div className="prose prose-lg text-gray-700">
|
||||
<p>
|
||||
Teljes DNS kezelés domain regisztrációval, átvitellel és professzionális beállításokkal.
|
||||
Gyors propagáció és megbízható névszerverek világszerte.
|
||||
</p>
|
||||
<h4 className="text-lg font-semibold text-gray-900 mt-6 mb-3">DNS szolgáltatások:</h4>
|
||||
<ul className="space-y-1">
|
||||
<li>Domain regisztráció (.hu, .com, .eu, stb.)</li>
|
||||
<li>Domain átvitel más szolgáltatótól</li>
|
||||
<li>DNS rekord kezelés (A, CNAME, MX, TXT)</li>
|
||||
<li>Subdomain beállítások</li>
|
||||
<li>Redirect és forwarding szolgáltatások</li>
|
||||
<li>DNSSEC támogatás</li>
|
||||
<li>API hozzáférés fejlesztőknek</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -168,24 +109,18 @@ export default function ServicesPage() {
|
||||
<section className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="bg-blue-50 rounded-xl p-8 text-center">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">
|
||||
Műszaki támogatás
|
||||
{pageContent.support.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-700 mb-6">
|
||||
Minden szolgáltatásunkhoz teljes körű műszaki támogatást biztosítunk
|
||||
{pageContent.support.subtitle}
|
||||
</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 text-sm">
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">Email támogatás</h3>
|
||||
<p className="text-gray-600">24 órán belüli válasz</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">Telefonos segítség</h3>
|
||||
<p className="text-gray-600">Munkaidőben elérhető</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">Sürgős esetek</h3>
|
||||
<p className="text-gray-600">Azonnali beavatkozás</p>
|
||||
</div>
|
||||
{pageContent.support.channels.map((channel) => (
|
||||
<div key={channel.title}>
|
||||
<h3 className="font-semibold text-gray-900 mb-2">{channel.title}</h3>
|
||||
<p className="text-gray-600">{channel.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -194,17 +129,17 @@ export default function ServicesPage() {
|
||||
<section className="bg-gray-900 text-white py-16">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl font-bold mb-4">
|
||||
Kezdjük el a közös munkát!
|
||||
{pageContent.cta.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-300 mb-8">
|
||||
Vegye fel velünk a kapcsolatot ingyenes konzultációért és egyedi ajánlatért.
|
||||
{pageContent.cta.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<a
|
||||
href="/kapcsolat"
|
||||
className="inline-block bg-blue-600 hover:bg-blue-700 text-white font-medium px-8 py-3 rounded-md transition-colors"
|
||||
>
|
||||
Kapcsolatfelvétel
|
||||
{pageContent.cta.primaryButton}
|
||||
</a>
|
||||
<a
|
||||
href={siteConfig.hero.cta.primary.href}
|
||||
@@ -212,7 +147,7 @@ export default function ServicesPage() {
|
||||
rel="noopener noreferrer"
|
||||
className="inline-block border-2 border-white text-white hover:bg-white hover:text-gray-900 font-medium px-8 py-3 rounded-md transition-colors"
|
||||
>
|
||||
Webmail belépés
|
||||
{pageContent.cta.secondaryButton}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+124
-25
@@ -1,36 +1,92 @@
|
||||
'use client'
|
||||
|
||||
import { siteConfig } from '@/config/site'
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-gray-50 border-t border-gray-200">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
||||
<footer
|
||||
className="border-t"
|
||||
style={{
|
||||
background: 'var(--color-background-secondary)',
|
||||
borderColor: 'var(--color-border)'
|
||||
}}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8 lg:gap-12">
|
||||
{/* Company Info */}
|
||||
<div className="md:col-span-2">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
||||
<a
|
||||
href="/"
|
||||
className="inline-flex items-center gap-2 text-xl font-bold mb-4 transition-colors duration-200"
|
||||
style={{ color: 'var(--color-primary-600)' }}
|
||||
>
|
||||
{siteConfig.general.name}
|
||||
</h3>
|
||||
<p className="text-gray-600 mb-4 max-w-md">
|
||||
<span
|
||||
className="inline-block w-2 h-2 rounded-full animate-pulse-slow"
|
||||
style={{ background: 'var(--color-success-500)' }}
|
||||
/>
|
||||
</a>
|
||||
<p
|
||||
className="mb-6 max-w-md leading-relaxed"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{siteConfig.general.description}
|
||||
</p>
|
||||
<div className="flex space-x-4">
|
||||
<div className="text-sm text-gray-500">
|
||||
<p>Email: {siteConfig.contact.email}</p>
|
||||
<p>Cég: {siteConfig.general.name}</p>
|
||||
<p>Székhely: {siteConfig.contact.address}</p>
|
||||
<div className="space-y-2 text-sm" style={{ color: 'var(--color-foreground-muted)' }}>
|
||||
<a
|
||||
href={`mailto:${siteConfig.contact.email}`}
|
||||
className="flex items-center gap-2 group transition-colors duration-200 hover:text-blue-600"
|
||||
style={{ color: 'var(--color-foreground-secondary)' }}
|
||||
>
|
||||
<span
|
||||
className="flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center transition-all duration-200 group-hover:scale-110"
|
||||
style={{ background: 'var(--color-primary-100)' }}
|
||||
>
|
||||
✉️
|
||||
</span>
|
||||
<span>{siteConfig.contact.email}</span>
|
||||
</a>
|
||||
<div
|
||||
className="flex items-center gap-2"
|
||||
style={{ color: 'var(--color-foreground-secondary)' }}
|
||||
>
|
||||
<span
|
||||
className="flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center"
|
||||
style={{ background: 'var(--color-primary-100)' }}
|
||||
>
|
||||
🏢
|
||||
</span>
|
||||
<span>{siteConfig.contact.address}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Links */}
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-gray-900 uppercase tracking-wide mb-4">
|
||||
<h3
|
||||
className="text-sm font-semibold uppercase tracking-wider mb-4"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
Navigáció
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
<ul className="space-y-3">
|
||||
{siteConfig.navigation.footer.map((item) => (
|
||||
<li key={item.href}>
|
||||
<a href={item.href} className="text-gray-600 hover:text-blue-600 transition-colors">
|
||||
<a
|
||||
href={item.href}
|
||||
className="group flex items-center gap-2 text-sm transition-all duration-200"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.color = 'var(--color-primary-600)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.color = 'var(--color-foreground-muted)'
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="w-1.5 h-1.5 rounded-full transition-all duration-200 group-hover:scale-150"
|
||||
style={{ background: 'var(--color-primary-500)' }}
|
||||
/>
|
||||
{item.label}
|
||||
</a>
|
||||
</li>
|
||||
@@ -40,32 +96,59 @@ export default function Footer() {
|
||||
|
||||
{/* Services */}
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-gray-900 uppercase tracking-wide mb-4">
|
||||
<h3
|
||||
className="text-sm font-semibold uppercase tracking-wider mb-4"
|
||||
style={{ color: 'var(--color-foreground)' }}
|
||||
>
|
||||
Szolgáltatások
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
<ul className="space-y-3">
|
||||
{siteConfig.services.services.map((service) => (
|
||||
<li key={service.id} className="text-gray-600">
|
||||
<li
|
||||
key={service.id}
|
||||
className="flex items-center gap-2 text-sm"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
<span className="text-base">{service.icon}</span>
|
||||
{service.title}
|
||||
</li>
|
||||
))}
|
||||
<li className="text-gray-600">Műszaki támogatás</li>
|
||||
<li
|
||||
className="flex items-center gap-2 text-sm"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
<span className="text-base">🛠️</span>
|
||||
Műszaki támogatás
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom section */}
|
||||
<div className="border-t border-gray-200 pt-8 mt-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-center">
|
||||
<p className="text-gray-500 text-sm">
|
||||
<div
|
||||
className="border-t pt-8 mt-8"
|
||||
style={{ borderColor: 'var(--color-border)' }}
|
||||
>
|
||||
<div className="flex flex-col sm:flex-row justify-between items-center gap-4">
|
||||
<p
|
||||
className="text-sm"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
>
|
||||
{siteConfig.footer.copyright}
|
||||
</p>
|
||||
<div className="flex space-x-4 mt-4 sm:mt-0">
|
||||
<div className="flex items-center gap-6">
|
||||
{siteConfig.footer.links.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-gray-500 hover:text-blue-600 text-sm transition-colors"
|
||||
className="text-sm transition-all duration-200 link-underline relative"
|
||||
style={{ color: 'var(--color-foreground-muted)' }}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.color = 'var(--color-primary-600)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.color = 'var(--color-foreground-muted)'
|
||||
}}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
@@ -73,7 +156,23 @@ export default function Footer() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tech badge */}
|
||||
<div className="mt-8 flex justify-center">
|
||||
<div
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-xs"
|
||||
style={{
|
||||
background: 'var(--color-background-tertiary)',
|
||||
color: 'var(--color-foreground-muted)'
|
||||
}}
|
||||
>
|
||||
<span>Powered by</span>
|
||||
<span className="font-medium" style={{ color: 'var(--color-foreground)' }}>Next.js</span>
|
||||
<span>•</span>
|
||||
<span className="font-medium" style={{ color: 'var(--color-foreground)' }}>Tailwind CSS</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+158
-45
@@ -1,93 +1,206 @@
|
||||
'use client'
|
||||
|
||||
import { siteConfig } from '@/config/site'
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { ThemeToggle } from './ThemeProvider'
|
||||
|
||||
export default function Header() {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
||||
const [isScrolled, setIsScrolled] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setIsScrolled(window.scrollY > 10)
|
||||
}
|
||||
window.addEventListener('scroll', handleScroll)
|
||||
return () => window.removeEventListener('scroll', handleScroll)
|
||||
}, [])
|
||||
|
||||
const toggleMenu = () => {
|
||||
setIsMenuOpen(!isMenuOpen)
|
||||
}
|
||||
|
||||
// Close menu on escape key
|
||||
useEffect(() => {
|
||||
const handleEscape = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') setIsMenuOpen(false)
|
||||
}
|
||||
document.addEventListener('keydown', handleEscape)
|
||||
return () => document.removeEventListener('keydown', handleEscape)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<header className="bg-white border-b border-gray-200 sticky top-0 z-50">
|
||||
<header
|
||||
className={`sticky top-0 z-50 transition-all duration-300 ${
|
||||
isScrolled
|
||||
? 'glass shadow-md'
|
||||
: ''
|
||||
}`}
|
||||
style={{
|
||||
background: isScrolled ? undefined : 'var(--color-background)',
|
||||
borderBottom: `1px solid var(--color-border)`,
|
||||
}}
|
||||
>
|
||||
<nav className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
{/* Logo */}
|
||||
<div className="flex-shrink-0">
|
||||
<a href="/" className="text-xl font-bold text-blue-600 hover:text-blue-700">
|
||||
{siteConfig.general.name}
|
||||
<a
|
||||
href="/"
|
||||
className="group flex items-center gap-2 text-xl font-bold transition-all duration-200"
|
||||
style={{ color: 'var(--color-primary-600)' }}
|
||||
>
|
||||
<span className="relative">
|
||||
<span className="group-hover:opacity-0 transition-opacity duration-200">
|
||||
{siteConfig.general.name}
|
||||
</span>
|
||||
<span
|
||||
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
|
||||
style={{ color: 'var(--color-primary-700)' }}
|
||||
>
|
||||
{siteConfig.general.name}
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
className="inline-block w-2 h-2 rounded-full animate-pulse-slow"
|
||||
style={{ background: 'var(--color-success-500)' }}
|
||||
title="Online"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:block">
|
||||
<div className="flex items-center space-x-8">
|
||||
{siteConfig.navigation.main.map((item) => (
|
||||
<a
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
target={item.external ? '_blank' : undefined}
|
||||
rel={item.external ? 'noopener noreferrer' : undefined}
|
||||
className={item.label === 'Kapcsolat'
|
||||
? "bg-blue-600 text-white px-4 py-2 rounded-md text-sm font-medium hover:bg-blue-700 transition-colors"
|
||||
: "text-gray-900 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors"
|
||||
}
|
||||
>
|
||||
<div className="hidden md:flex items-center space-x-1">
|
||||
{siteConfig.navigation.main.map((item, index) => (
|
||||
<a
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
target={item.external ? '_blank' : undefined}
|
||||
rel={item.external ? 'noopener noreferrer' : undefined}
|
||||
className={`relative px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200 ${
|
||||
item.label === 'Kapcsolat'
|
||||
? 'btn btn-primary text-white'
|
||||
: 'hover-scale'
|
||||
}`}
|
||||
style={item.label !== 'Kapcsolat' ? {
|
||||
color: 'var(--color-foreground)',
|
||||
} : undefined}
|
||||
>
|
||||
{item.label !== 'Kapcsolat' && (
|
||||
<span
|
||||
className="absolute inset-0 rounded-lg opacity-0 hover:opacity-100 transition-opacity duration-200"
|
||||
style={{ background: 'var(--color-primary-50)' }}
|
||||
/>
|
||||
)}
|
||||
<span className="relative z-10">
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
{item.external && (
|
||||
<svg className="inline-block w-3 h-3 ml-1 -mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
)}
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
|
||||
{/* Theme Toggle */}
|
||||
<div className="ml-2 pl-2" style={{ borderLeft: `1px solid var(--color-border)` }}>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden">
|
||||
<div className="md:hidden flex items-center gap-2">
|
||||
<ThemeToggle />
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleMenu}
|
||||
className="text-gray-500 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500"
|
||||
className="p-2 rounded-lg transition-all duration-200"
|
||||
style={{
|
||||
color: 'var(--color-foreground-muted)',
|
||||
background: isMenuOpen ? 'var(--color-background-tertiary)' : 'transparent'
|
||||
}}
|
||||
aria-expanded={isMenuOpen}
|
||||
>
|
||||
<span className="sr-only">{isMenuOpen ? 'Close main menu' : 'Open main menu'}</span>
|
||||
{isMenuOpen ? (
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
)}
|
||||
<div className="relative w-6 h-6">
|
||||
{/* Hamburger to X animation */}
|
||||
<span
|
||||
className={`absolute h-0.5 w-6 rounded-full transform transition-all duration-300 ${
|
||||
isMenuOpen ? 'rotate-45 top-3' : 'rotate-0 top-1'
|
||||
}`}
|
||||
style={{ background: 'currentColor' }}
|
||||
/>
|
||||
<span
|
||||
className={`absolute h-0.5 w-6 rounded-full top-3 transition-all duration-200 ${
|
||||
isMenuOpen ? 'opacity-0 translate-x-2' : 'opacity-100'
|
||||
}`}
|
||||
style={{ background: 'currentColor' }}
|
||||
/>
|
||||
<span
|
||||
className={`absolute h-0.5 w-6 rounded-full transform transition-all duration-300 ${
|
||||
isMenuOpen ? '-rotate-45 top-3' : 'rotate-0 top-5'
|
||||
}`}
|
||||
style={{ background: 'currentColor' }}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation - Dynamic visibility */}
|
||||
<div className={`md:hidden absolute top-full left-0 right-0 bg-white border-b border-gray-200 shadow-lg transition-all duration-300 ease-in-out ${
|
||||
isMenuOpen
|
||||
? 'opacity-100 visible'
|
||||
: 'opacity-0 invisible'
|
||||
}`}>
|
||||
<div className="px-2 pt-2 pb-3 space-y-1">
|
||||
{siteConfig.navigation.main.map((item) => (
|
||||
{/* Mobile Navigation */}
|
||||
<div
|
||||
className={`md:hidden overflow-hidden transition-all duration-300 ease-in-out ${
|
||||
isMenuOpen ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="py-3 space-y-1 border-t"
|
||||
style={{ borderColor: 'var(--color-border)' }}
|
||||
>
|
||||
{siteConfig.navigation.main.map((item, index) => (
|
||||
<a
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
target={item.external ? '_blank' : undefined}
|
||||
rel={item.external ? 'noopener noreferrer' : undefined}
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
className={item.label === 'Kapcsolat'
|
||||
? "block px-3 py-2 rounded-md text-base font-medium bg-blue-600 text-white"
|
||||
: "block px-3 py-2 rounded-md text-base font-medium text-gray-900 hover:text-blue-600 hover:bg-blue-50"
|
||||
}
|
||||
className={`block px-4 py-3 rounded-lg text-base font-medium transition-all duration-200 ${
|
||||
item.label === 'Kapcsolat' ? 'btn btn-primary text-white mt-2' : ''
|
||||
}`}
|
||||
style={{
|
||||
animationDelay: `${index * 50}ms`,
|
||||
...(item.label !== 'Kapcsolat' ? {
|
||||
color: 'var(--color-foreground)',
|
||||
background: 'transparent',
|
||||
} : {})
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
if (item.label !== 'Kapcsolat') {
|
||||
e.currentTarget.style.background = 'var(--color-primary-50)'
|
||||
e.currentTarget.style.color = 'var(--color-primary-600)'
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (item.label !== 'Kapcsolat') {
|
||||
e.currentTarget.style.background = 'transparent'
|
||||
e.currentTarget.style.color = 'var(--color-foreground)'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
<span className="flex items-center justify-between">
|
||||
{item.label}
|
||||
{item.external && (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
)}
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
'use client'
|
||||
|
||||
import { createContext, useContext, useEffect, useState, ReactNode } from 'react'
|
||||
|
||||
type Theme = 'light' | 'dark' | 'system'
|
||||
|
||||
interface ThemeContextType {
|
||||
theme: Theme
|
||||
resolvedTheme: 'light' | 'dark'
|
||||
setTheme: (theme: Theme) => void
|
||||
toggleTheme: () => void
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
|
||||
|
||||
export function useTheme() {
|
||||
const context = useContext(ThemeContext)
|
||||
if (!context) {
|
||||
// Return default values when not in provider (SSR/prerendering)
|
||||
return {
|
||||
theme: 'system' as const,
|
||||
resolvedTheme: 'light' as const,
|
||||
setTheme: () => {},
|
||||
toggleTheme: () => {},
|
||||
}
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
interface ThemeProviderProps {
|
||||
children: ReactNode
|
||||
defaultTheme?: Theme
|
||||
}
|
||||
|
||||
export function ThemeProvider({ children, defaultTheme = 'system' }: ThemeProviderProps) {
|
||||
const [theme, setThemeState] = useState<Theme>(defaultTheme)
|
||||
const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light')
|
||||
const [mounted, setMounted] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true)
|
||||
const savedTheme = localStorage.getItem('theme') as Theme | null
|
||||
if (savedTheme) {
|
||||
setThemeState(savedTheme)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted) return
|
||||
|
||||
const root = document.documentElement
|
||||
let resolved: 'light' | 'dark'
|
||||
|
||||
if (theme === 'system') {
|
||||
resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
root.removeAttribute('data-theme')
|
||||
} else {
|
||||
resolved = theme
|
||||
root.setAttribute('data-theme', theme)
|
||||
}
|
||||
|
||||
setResolvedTheme(resolved)
|
||||
}, [theme, mounted])
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted) return
|
||||
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
const handleChange = (e: MediaQueryListEvent) => {
|
||||
if (theme === 'system') {
|
||||
setResolvedTheme(e.matches ? 'dark' : 'light')
|
||||
}
|
||||
}
|
||||
|
||||
mediaQuery.addEventListener('change', handleChange)
|
||||
return () => mediaQuery.removeEventListener('change', handleChange)
|
||||
}, [theme, mounted])
|
||||
|
||||
const setTheme = (newTheme: Theme) => {
|
||||
setThemeState(newTheme)
|
||||
localStorage.setItem('theme', newTheme)
|
||||
}
|
||||
|
||||
const toggleTheme = () => {
|
||||
const newTheme = resolvedTheme === 'light' ? 'dark' : 'light'
|
||||
setTheme(newTheme)
|
||||
}
|
||||
|
||||
// Prevent hydration mismatch - render children without context until mounted
|
||||
if (!mounted) {
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme, resolvedTheme, setTheme, toggleTheme }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
// Theme toggle button component
|
||||
export function ThemeToggle() {
|
||||
const { resolvedTheme, toggleTheme } = useTheme()
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="relative p-2 rounded-lg bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all duration-200 group"
|
||||
style={{
|
||||
background: resolvedTheme === 'dark' ? 'var(--color-background-tertiary)' : 'var(--color-background-tertiary)',
|
||||
}}
|
||||
aria-label={resolvedTheme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'}
|
||||
>
|
||||
{/* Sun icon */}
|
||||
<svg
|
||||
className={`w-5 h-5 transition-all duration-300 ${
|
||||
resolvedTheme === 'dark'
|
||||
? 'opacity-0 rotate-90 scale-0'
|
||||
: 'opacity-100 rotate-0 scale-100'
|
||||
}`}
|
||||
style={{ color: 'var(--color-foreground)', position: resolvedTheme === 'dark' ? 'absolute' : 'relative' }}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
|
||||
/>
|
||||
</svg>
|
||||
{/* Moon icon */}
|
||||
<svg
|
||||
className={`w-5 h-5 transition-all duration-300 ${
|
||||
resolvedTheme === 'dark'
|
||||
? 'opacity-100 rotate-0 scale-100'
|
||||
: 'opacity-0 -rotate-90 scale-0'
|
||||
}`}
|
||||
style={{ color: 'var(--color-foreground)', position: resolvedTheme === 'light' ? 'absolute' : 'relative' }}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"buttons": {
|
||||
"contact": "Kapcsolatfelvétel",
|
||||
"learnMore": "További információk",
|
||||
"webmail": "Webmail belépés",
|
||||
"sendMessage": "Üzenet küldése"
|
||||
},
|
||||
"labels": {
|
||||
"required": "*",
|
||||
"features": "Szolgáltatás jellemzők:"
|
||||
},
|
||||
"validation": {
|
||||
"required": "Ez a mező kötelező",
|
||||
"invalidEmail": "Érvénytelen email cím formátum",
|
||||
"minLength": "Legalább {min} karakter szükséges"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Content Loader - Centralized content management
|
||||
*
|
||||
* This module provides type-safe access to all JSON content files.
|
||||
* Content can be easily modified by editing the JSON files without code changes.
|
||||
*
|
||||
* Usage:
|
||||
* import { content, getPageContent } from '@/content'
|
||||
*
|
||||
* // Access specific page content
|
||||
* const aboutContent = content.pages.about
|
||||
*
|
||||
* // Or use the helper function
|
||||
* const servicesContent = getPageContent('services')
|
||||
*/
|
||||
|
||||
import type {
|
||||
SiteContent,
|
||||
CommonContent,
|
||||
HomePageContent,
|
||||
AboutPageContent,
|
||||
ServicesPageContent,
|
||||
ContactPageContent
|
||||
} from './types'
|
||||
|
||||
// Import JSON files
|
||||
import commonJson from './common.json'
|
||||
import homeJson from './pages/home.json'
|
||||
import aboutJson from './pages/about.json'
|
||||
import servicesJson from './pages/services.json'
|
||||
import contactJson from './pages/contact.json'
|
||||
|
||||
// Type assertions for JSON imports
|
||||
const common: CommonContent = commonJson as CommonContent
|
||||
const home: HomePageContent = homeJson as HomePageContent
|
||||
const about: AboutPageContent = aboutJson as AboutPageContent
|
||||
const services: ServicesPageContent = servicesJson as ServicesPageContent
|
||||
const contact: ContactPageContent = contactJson as ContactPageContent
|
||||
|
||||
// Combined content object
|
||||
export const content: SiteContent = {
|
||||
common,
|
||||
pages: {
|
||||
home,
|
||||
about,
|
||||
services,
|
||||
contact
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to get page content with type safety
|
||||
export function getPageContent<T extends keyof SiteContent['pages']>(
|
||||
page: T
|
||||
): SiteContent['pages'][T] {
|
||||
return content.pages[page]
|
||||
}
|
||||
|
||||
// Export individual content for direct imports
|
||||
export { common, home, about, services, contact }
|
||||
|
||||
// Re-export types
|
||||
export * from './types'
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Rólunk",
|
||||
"description": "Ismerje meg a mozdIT Bt. történetét, küldetését és értékeit. Több mint 10 éve nyújtunk megbízható IT szolgáltatásokat.",
|
||||
"ogDescription": "Ismerje meg a mozdIT Bt. történetét, küldetését és értékeit."
|
||||
},
|
||||
"hero": {
|
||||
"title": "Rólunk",
|
||||
"subtitle": "Több mint 10 éve biztosítunk megbízható IT infrastruktúrát és személyes ügyfélszolgálatot"
|
||||
},
|
||||
"story": {
|
||||
"title": "Történetünk",
|
||||
"paragraphs": [
|
||||
"A <strong>mozdIT Bt.</strong> 2010-ben alakult azzal a céllal, hogy kisvállalkozások és magánszemélyek számára nyújtson megbízható, személyes IT szolgáltatásokat. Alapítóink több évtizedes tapasztalattal rendelkeznek a rendszeradminisztráció és webfejlesztés területén.",
|
||||
"Kezdetben néhány ügyfél weboldalának üzemeltetésével indultunk, ma pedig több száz domain és email fiók működését biztosítjuk. Növekedésünk során mindig szem előtt tartottuk az alapelveinket: <em>megbízhatóság, személyes kapcsolat és műszaki kiválóság</em>.",
|
||||
"Csapatunk folyamatosan képezi magát a legújabb technológiák terén, hogy ügyfeleink mindig korszerű és biztonságos megoldásokat kapjanak. Büszkék vagyunk arra, hogy sok ügyfelünkkel évek óta tartjuk a kapcsolatot, és számos projektet vittünk sikerre közösen."
|
||||
]
|
||||
},
|
||||
"mission": {
|
||||
"title": "Küldetésünk és értékeink",
|
||||
"subtitle": "Minden nap azért dolgozunk, hogy ügyfeleink digitális jelenléte biztonságos, stabil és hatékony legyen.",
|
||||
"values": [
|
||||
{
|
||||
"icon": "🛡️",
|
||||
"title": "Megbízhatóság",
|
||||
"description": "99.9% uptime és 24/7 monitoring biztosítja, hogy szolgáltatásaink mindig elérhetők legyenek."
|
||||
},
|
||||
{
|
||||
"icon": "👥",
|
||||
"title": "Személyes kapcsolat",
|
||||
"description": "Minden ügyfél számít számunkra. Személyre szabott megoldásokat kínálunk és mindig elérhetők vagyunk."
|
||||
},
|
||||
{
|
||||
"icon": "⚡",
|
||||
"title": "Műszaki kiválóság",
|
||||
"description": "Korszerű technológiák és bevált gyakorlatok alkalmazásával biztosítjuk a legmagasabb színvonalú szolgáltatást."
|
||||
}
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"title": "Szakértő csapat",
|
||||
"subtitle": "Tapasztalt IT szakemberek, akik szenvedélyesen dolgoznak az ügyfeleink sikeréért",
|
||||
"paragraphs": [
|
||||
"Csapatunk rendszeradminisztrátorokból, webfejlesztőkből és ügyfélszolgálati szakértőkből áll. Mindannyian több mint 10 éves tapasztalattal rendelkeznek a maguk területén, és folyamatosan követik a technológiai újdonságokat.",
|
||||
"Hiszünk abban, hogy a jó kommunikáció és a műszaki tudás együtt teremti meg a tökéletes ügyfélélményt. Ezért minden munkatársunk nemcsak technikai szakértő, hanem kiváló kommunikátor is."
|
||||
]
|
||||
},
|
||||
"cta": {
|
||||
"title": "Legyen Ön is elégedett ügyfelünk!",
|
||||
"subtitle": "Vegye fel velünk a kapcsolatot, és beszéljük meg, hogyan segíthetünk Önnek.",
|
||||
"button": "Kapcsolatfelvétel"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Kapcsolat",
|
||||
"description": "Vegye fel velünk a kapcsolatot! Szívesen segítünk minden IT kérdésében."
|
||||
},
|
||||
"hero": {
|
||||
"title": "Kapcsolat",
|
||||
"subtitle": "Vegye fel velünk a kapcsolatot! Szívesen segítünk minden IT kérdésében."
|
||||
},
|
||||
"form": {
|
||||
"title": "Küldjön üzenetet",
|
||||
"successMessage": "Köszönjük üzenetét! Hamarosan felvesszük Önnel a kapcsolatot.",
|
||||
"errorMessage": "Hiba történt az üzenet küldése során. Kérjük, próbálja újra vagy írjon közvetlenül a {email} címre.",
|
||||
"fields": {
|
||||
"name": {
|
||||
"label": "Név",
|
||||
"placeholder": "Az Ön neve",
|
||||
"error": "A név megadása kötelező"
|
||||
},
|
||||
"email": {
|
||||
"label": "Email cím",
|
||||
"placeholder": "pelda@email.hu",
|
||||
"errorRequired": "Az email cím megadása kötelező",
|
||||
"errorInvalid": "Érvénytelen email cím formátum"
|
||||
},
|
||||
"subject": {
|
||||
"label": "Tárgy",
|
||||
"placeholder": "Miben segíthetünk?",
|
||||
"error": "A tárgy megadása kötelező"
|
||||
},
|
||||
"message": {
|
||||
"label": "Üzenet",
|
||||
"placeholder": "Írja le részletesen kérését vagy kérdését...",
|
||||
"errorRequired": "Az üzenet megadása kötelező",
|
||||
"errorMinLength": "Az üzenet legalább 10 karakter hosszú legyen"
|
||||
},
|
||||
"gdpr": {
|
||||
"label": "Elfogadom az <a href=\"/adatkezelesi-tajekoztato\" class=\"text-blue-600 hover:text-blue-700 underline\">adatkezelési tájékoztatót</a> és hozzájárulok személyes adataim kezeléséhez a kapcsolatfelvétel céljából.",
|
||||
"error": "Az adatkezelési tájékoztató elfogadása kötelező"
|
||||
}
|
||||
},
|
||||
"submitButton": "Üzenet küldése",
|
||||
"submittingButton": "Küldés..."
|
||||
},
|
||||
"info": {
|
||||
"title": "Elérhetőségek",
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"responseTime": "24 órán belül válaszolunk"
|
||||
},
|
||||
"company": {
|
||||
"title": "Cég"
|
||||
},
|
||||
"webmail": {
|
||||
"title": "Webmail hozzáférés",
|
||||
"linkText": "Webmail belépés →",
|
||||
"subtitle": "Ügyfeleink számára"
|
||||
}
|
||||
},
|
||||
"faq": {
|
||||
"title": "Gyakori kérdések",
|
||||
"items": [
|
||||
{
|
||||
"question": "Milyen gyorsan válaszolnak?",
|
||||
"answer": "Email üzenetekre 24 órán belül, sürgős esetekben telefonon is elérhetők vagyunk."
|
||||
},
|
||||
{
|
||||
"question": "Van ingyenes konzultáció?",
|
||||
"answer": "Igen! Az első konzultáció mindig ingyenes, hogy megismerjük az Ön igényeit."
|
||||
},
|
||||
{
|
||||
"question": "Milyen fizetési módokat fogadnak el?",
|
||||
"answer": "Banki átutalás, PayPal és kártyás fizetés is lehetséges."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"cta": {
|
||||
"title": "Kapcsolatfelvétel az első lépés",
|
||||
"subtitle": "Mutassuk meg, hogyan segíthetünk Önnek megvalósítani céljait!",
|
||||
"button": "Kapcsolatfelvétel"
|
||||
},
|
||||
"serviceFeatures": {
|
||||
"title": "Szolgáltatás jellemzők:"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Szolgáltatások",
|
||||
"description": "Webhosting, email szolgáltatás és DNS adminisztráció professzionális szinten. Ismerje meg részletes szolgáltatásainkat.",
|
||||
"ogDescription": "Webhosting, email szolgáltatás és DNS adminisztráció professzionális szinten."
|
||||
},
|
||||
"hero": {
|
||||
"title": "Szolgáltatásaink",
|
||||
"subtitle": "Teljes körű IT megoldások kisvállalkozások és magánszemélyek számára"
|
||||
},
|
||||
"details": {
|
||||
"title": "Részletes szolgáltatásleírás",
|
||||
"subtitle": "Minden szolgáltatásunk mögött évtizedes tapasztalat és modern technológia áll",
|
||||
"services": [
|
||||
{
|
||||
"icon": "🌐",
|
||||
"title": "Web Hosting részletesen",
|
||||
"description": "Weboldalak biztonságos és gyors üzemeltetése SSD tárolással, automatikus biztonsági mentéssel és 24/7 monitoringgal. Támogatjuk a PHP, Python, Node.js technológiákat és MySQL/PostgreSQL adatbázisokat.",
|
||||
"specs": {
|
||||
"title": "Technikai specifikációk:",
|
||||
"items": [
|
||||
"SSD tárhely 10GB-tól 500GB-ig",
|
||||
"Havi adatforgalom: korlátlan",
|
||||
"SSL tanúsítványok (Let's Encrypt vagy prémium)",
|
||||
"CDN integráció a gyorsabb betöltésért",
|
||||
"Automatikus napi biztonsági mentés",
|
||||
"cPanel vagy egyedi admin felület"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "✉️",
|
||||
"title": "Email szolgáltatás részletesen",
|
||||
"description": "Professzionális email fiókok saját domain névvel, spam szűréssel és vírusvédelemmel. Webmail felület és IMAP/POP3/SMTP támogatás minden népszerű email klienssel.",
|
||||
"specs": {
|
||||
"title": "Email funkciók:",
|
||||
"items": [
|
||||
"Korlátlan email fiókok létrehozása",
|
||||
"5GB-50GB tárhelyet fiókként",
|
||||
"Webmail hozzáférés (Roundcube/SOGo)",
|
||||
"Mobilalkalmazás szinkronizáció",
|
||||
"Spam és vírusszűrés",
|
||||
"Email továbbítás és automatikus válaszok",
|
||||
"Backup és archiválás"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "⚙️",
|
||||
"title": "DNS adminisztráció részletesen",
|
||||
"description": "Teljes DNS kezelés domain regisztrációval, átvitellel és professzionális beállításokkal. Gyors propagáció és megbízható névszerverek világszerte.",
|
||||
"specs": {
|
||||
"title": "DNS szolgáltatások:",
|
||||
"items": [
|
||||
"Domain regisztráció (.hu, .com, .eu, stb.)",
|
||||
"Domain átvitel más szolgáltatótól",
|
||||
"DNS rekord kezelés (A, CNAME, MX, TXT)",
|
||||
"Subdomain beállítások",
|
||||
"Redirect és forwarding szolgáltatások",
|
||||
"DNSSEC támogatás",
|
||||
"API hozzáférés fejlesztőknek"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"support": {
|
||||
"title": "Műszaki támogatás",
|
||||
"subtitle": "Minden szolgáltatásunkhoz teljes körű műszaki támogatást biztosítunk",
|
||||
"channels": [
|
||||
{
|
||||
"icon": "✉️",
|
||||
"title": "Email támogatás",
|
||||
"description": "24 órán belüli válasz"
|
||||
},
|
||||
{
|
||||
"icon": "📞",
|
||||
"title": "Telefonos segítség",
|
||||
"description": "Munkaidőben elérhető"
|
||||
},
|
||||
{
|
||||
"icon": "🚨",
|
||||
"title": "Sürgős esetek",
|
||||
"description": "Azonnali beavatkozás"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cta": {
|
||||
"title": "Kezdjük el a közös munkát!",
|
||||
"subtitle": "Vegye fel velünk a kapcsolatot ingyenes konzultációért és egyedi ajánlatért.",
|
||||
"primaryButton": "Kapcsolatfelvétel",
|
||||
"secondaryButton": "Webmail belépés"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Content Types - TypeScript definitions for JSON content files
|
||||
* These types ensure type safety when working with page content
|
||||
*/
|
||||
|
||||
// Common content types
|
||||
export interface CTAContent {
|
||||
text: string
|
||||
href: string
|
||||
external?: boolean
|
||||
}
|
||||
|
||||
export interface IconTextItem {
|
||||
icon: string
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface FAQItem {
|
||||
question: string
|
||||
answer: string
|
||||
}
|
||||
|
||||
export interface TechSpec {
|
||||
title: string
|
||||
items: string[]
|
||||
}
|
||||
|
||||
// Page-specific content types
|
||||
export interface HomePageContent {
|
||||
cta: {
|
||||
title: string
|
||||
subtitle: string
|
||||
button: string
|
||||
}
|
||||
serviceFeatures: {
|
||||
title: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface AboutPageContent {
|
||||
meta: {
|
||||
title: string
|
||||
description: string
|
||||
ogDescription: string
|
||||
}
|
||||
hero: {
|
||||
title: string
|
||||
subtitle: string
|
||||
}
|
||||
story: {
|
||||
title: string
|
||||
paragraphs: string[]
|
||||
}
|
||||
mission: {
|
||||
title: string
|
||||
subtitle: string
|
||||
values: IconTextItem[]
|
||||
}
|
||||
team: {
|
||||
title: string
|
||||
subtitle: string
|
||||
paragraphs: string[]
|
||||
}
|
||||
cta: {
|
||||
title: string
|
||||
subtitle: string
|
||||
button: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServiceDetailContent {
|
||||
icon: string
|
||||
title: string
|
||||
description: string
|
||||
specs: TechSpec
|
||||
}
|
||||
|
||||
export interface ServicesPageContent {
|
||||
meta: {
|
||||
title: string
|
||||
description: string
|
||||
ogDescription: string
|
||||
}
|
||||
hero: {
|
||||
title: string
|
||||
subtitle: string
|
||||
}
|
||||
details: {
|
||||
title: string
|
||||
subtitle: string
|
||||
services: ServiceDetailContent[]
|
||||
}
|
||||
support: {
|
||||
title: string
|
||||
subtitle: string
|
||||
channels: IconTextItem[]
|
||||
}
|
||||
cta: {
|
||||
title: string
|
||||
subtitle: string
|
||||
primaryButton: string
|
||||
secondaryButton: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ContactPageContent {
|
||||
meta: {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
hero: {
|
||||
title: string
|
||||
subtitle: string
|
||||
}
|
||||
form: {
|
||||
title: string
|
||||
successMessage: string
|
||||
errorMessage: string
|
||||
fields: {
|
||||
name: { label: string; placeholder: string; error: string }
|
||||
email: { label: string; placeholder: string; errorRequired: string; errorInvalid: string }
|
||||
subject: { label: string; placeholder: string; error: string }
|
||||
message: { label: string; placeholder: string; errorRequired: string; errorMinLength: string }
|
||||
gdpr: { label: string; error: string }
|
||||
}
|
||||
submitButton: string
|
||||
submittingButton: string
|
||||
}
|
||||
info: {
|
||||
title: string
|
||||
email: {
|
||||
title: string
|
||||
responseTime: string
|
||||
}
|
||||
company: {
|
||||
title: string
|
||||
}
|
||||
webmail: {
|
||||
title: string
|
||||
linkText: string
|
||||
subtitle: string
|
||||
}
|
||||
}
|
||||
faq: {
|
||||
title: string
|
||||
items: FAQItem[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface CommonContent {
|
||||
buttons: {
|
||||
contact: string
|
||||
learnMore: string
|
||||
webmail: string
|
||||
sendMessage: string
|
||||
}
|
||||
labels: {
|
||||
required: string
|
||||
features: string
|
||||
}
|
||||
validation: {
|
||||
required: string
|
||||
invalidEmail: string
|
||||
minLength: string
|
||||
}
|
||||
}
|
||||
|
||||
// Main content structure
|
||||
export interface SiteContent {
|
||||
common: CommonContent
|
||||
pages: {
|
||||
home: HomePageContent
|
||||
about: AboutPageContent
|
||||
services: ServicesPageContent
|
||||
contact: ContactPageContent
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,9 +7,9 @@
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
|
||||
Reference in New Issue
Block a user