huge update

This commit is contained in:
2025-09-10 10:59:14 +02:00
parent be01ee2adb
commit 2f40fc6753
15 changed files with 729 additions and 301 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { useState, useEffect, useCallback } from 'react';
import { motion } from 'framer-motion';
import {
BarChart3,
@@ -8,16 +8,12 @@ import {
Eye,
Heart,
Zap,
Users,
Clock,
Globe,
Activity,
Target,
Award,
RefreshCw,
Calendar,
MousePointer,
Monitor,
RotateCcw,
Trash2,
AlertTriangle
@@ -76,7 +72,7 @@ export function AnalyticsDashboard({ isAuthenticated }: AnalyticsDashboardProps)
const [resetType, setResetType] = useState<'analytics' | 'pageviews' | 'interactions' | 'performance' | 'all'>('analytics');
const [resetting, setResetting] = useState(false);
const fetchAnalyticsData = async () => {
const fetchAnalyticsData = useCallback(async () => {
if (!isAuthenticated) return;
try {
@@ -132,7 +128,7 @@ export function AnalyticsDashboard({ isAuthenticated }: AnalyticsDashboardProps)
} finally {
setLoading(false);
}
};
}, [isAuthenticated]);
const resetAnalytics = async () => {
if (!isAuthenticated || resetting) return;
@@ -167,7 +163,7 @@ export function AnalyticsDashboard({ isAuthenticated }: AnalyticsDashboardProps)
if (isAuthenticated) {
fetchAnalyticsData();
}
}, [isAuthenticated, timeRange]);
}, [isAuthenticated, fetchAnalyticsData]);
const StatCard = ({ title, value, icon: Icon, color, trend, trendValue, description }: {
title: string;
@@ -530,7 +526,7 @@ export function AnalyticsDashboard({ isAuthenticated }: AnalyticsDashboardProps)
<label className="block text-white/80 text-sm mb-2">Reset Type</label>
<select
value={resetType}
onChange={(e) => setResetType(e.target.value as any)}
onChange={(e) => setResetType(e.target.value as 'all' | 'performance' | 'analytics')}
className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-red-500"
>
<option value="analytics">Analytics Only (views, likes, shares)</option>

View File

@@ -5,11 +5,7 @@ import { motion, AnimatePresence } from 'framer-motion';
import {
Mail,
Search,
Filter,
Reply,
Archive,
Trash2,
Clock,
User,
CheckCircle,
Circle,
@@ -54,7 +50,7 @@ export const EmailManager: React.FC = () => {
if (response.ok) {
const data = await response.json();
const formattedMessages = data.contacts.map((contact: any) => ({
const formattedMessages = data.contacts.map((contact: ContactMessage) => ({
id: contact.id.toString(),
name: contact.name,
email: contact.email,
@@ -141,6 +137,7 @@ export const EmailManager: React.FC = () => {
});
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getPriorityColor = (priority: string) => {
switch (priority) {
case 'high': return 'text-red-400';
@@ -195,7 +192,7 @@ export const EmailManager: React.FC = () => {
{['all', 'unread', 'responded'].map((filterType) => (
<button
key={filterType}
onClick={() => setFilter(filterType as any)}
onClick={() => setFilter(filterType as 'all' | 'unread' | 'responded')}
className={`px-4 py-2 rounded-lg transition-colors ${
filter === filterType
? 'bg-blue-500 text-white'

View File

@@ -6,37 +6,21 @@ import {
Save,
X,
Eye,
EyeOff,
Settings,
Link as LinkIcon,
Tag,
Calendar,
Globe,
Github,
Image as ImageIcon,
Bold,
Italic,
List,
Hash,
Quote,
Code,
Zap,
Type,
Columns,
PanelLeft,
PanelRight,
Monitor,
Smartphone,
Tablet,
Undo,
Redo,
AlignLeft,
AlignCenter,
AlignRight,
Link2,
ListOrdered,
Underline,
Strikethrough
Strikethrough,
Type,
Columns
} from 'lucide-react';
interface Project {
@@ -60,7 +44,7 @@ interface GhostEditorProps {
isOpen: boolean;
onClose: () => void;
project?: Project | null;
onSave: (projectData: any) => void;
onSave: (projectData: Partial<Project>) => void;
isCreating: boolean;
}
@@ -251,7 +235,7 @@ export const GhostEditor: React.FC<GhostEditorProps> = ({
// Render markdown preview
const renderMarkdownPreview = (markdown: string) => {
// Simple markdown renderer for preview
let html = markdown
const html = markdown
// Headers
.replace(/^### (.*$)/gim, '<h3 class="text-xl font-semibold text-white mb-3 mt-6">$1</h3>')
.replace(/^## (.*$)/gim, '<h2 class="text-2xl font-bold text-white mb-4 mt-8">$1</h2>')

View File

@@ -7,8 +7,6 @@ import {
Settings,
TrendingUp,
Plus,
Edit,
Trash2,
Shield,
Users,
Activity,
@@ -56,6 +54,7 @@ interface ModernAdminDashboardProps {
const ModernAdminDashboard: React.FC<ModernAdminDashboardProps> = ({ isAuthenticated = true }) => {
const [activeTab, setActiveTab] = useState<'overview' | 'projects' | 'emails' | 'analytics' | 'settings'>('overview');
const [projects, setProjects] = useState<Project[]>([]);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [isLoading, setIsLoading] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [analytics, setAnalytics] = useState<Record<string, unknown> | null>(null);
@@ -540,7 +539,7 @@ const ModernAdminDashboard: React.FC<ModernAdminDashboardProps> = ({ isAuthentic
</div>
</div>
<ProjectManager isAuthenticated={isAuthenticated} projects={projects} onProjectsChange={loadProjects} />
<ProjectManager projects={projects} onProjectsChange={loadProjects} />
</div>
)}

View File

@@ -1,29 +1,16 @@
'use client';
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import React, { useState } from 'react';
import { motion } from 'framer-motion';
import {
Plus,
Edit,
Trash2,
Eye,
Search,
Filter,
Grid,
List,
Save,
X,
Upload,
Image as ImageIcon,
Link as LinkIcon,
Globe,
Github,
Calendar,
Tag,
Star,
TrendingUp,
Settings,
MoreVertical,
RefreshCw
} from 'lucide-react';
// Editor is now a separate page at /editor
@@ -54,13 +41,11 @@ interface Project {
}
interface ProjectManagerProps {
isAuthenticated: boolean;
projects: Project[];
onProjectsChange: () => void;
}
export const ProjectManager: React.FC<ProjectManagerProps> = ({
isAuthenticated,
projects,
onProjectsChange
}) => {
@@ -70,7 +55,6 @@ export const ProjectManager: React.FC<ProjectManagerProps> = ({
// Editor is now a separate page - no modal state needed
const categories = ['all', 'Web Development', 'Full-Stack', 'Web Application', 'Mobile App', 'Design'];
const difficulties = ['Beginner', 'Intermediate', 'Advanced', 'Expert'];
// Filter projects
const filteredProjects = projects.filter((project) => {

View File

@@ -8,36 +8,19 @@ import {
Eye,
EyeOff,
Settings,
Link as LinkIcon,
Tag,
Calendar,
Globe,
Github,
Image as ImageIcon,
Bold,
Italic,
List,
Hash,
Quote,
Code,
Zap,
Type,
Columns,
PanelLeft,
PanelRight,
Monitor,
Smartphone,
Tablet,
Undo,
Redo,
AlignLeft,
AlignCenter,
AlignRight,
Link2,
ListOrdered,
Underline,
Strikethrough,
GripVertical
GripVertical,
Image as ImageIcon
} from 'lucide-react';
interface Project {
@@ -59,7 +42,7 @@ interface Project {
interface ResizableGhostEditorProps {
project?: Project | null;
onSave: (projectData: any) => void;
onSave: (projectData: Partial<Project>) => void;
onClose: () => void;
isCreating: boolean;
}
@@ -277,7 +260,7 @@ export const ResizableGhostEditor: React.FC<ResizableGhostEditorProps> = ({
// Enhanced markdown renderer with proper white text
const renderMarkdownPreview = (markdown: string) => {
let html = markdown
const html = markdown
// Headers - WHITE TEXT
.replace(/^### (.*$)/gim, '<h3 class="text-xl font-semibold text-white mb-3 mt-6">$1</h3>')
.replace(/^## (.*$)/gim, '<h2 class="text-2xl font-bold text-white mb-4 mt-8">$1</h2>')