lucide-react komponenti kaldırıldı.
This commit is contained in:
parent
4fada60029
commit
8ddede546d
61 changed files with 877 additions and 11810 deletions
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
|||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.7jvpk79jec"
|
||||
"revision": "0.mmr753hmff"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
|
|
|||
11051
ui/package-lock.json
generated
11051
ui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -45,7 +45,6 @@
|
|||
"jspdf": "^3.0.1",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.484.0",
|
||||
"react": "^18.3.1",
|
||||
"react-advanced-cropper": "^0.20.0",
|
||||
"react-arborist": "^3.4.0",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react'
|
|||
import Editor from '@monaco-editor/react'
|
||||
import { ComponentDefinition } from '../../@types/componentInfo'
|
||||
import { generateSingleComponentJSX, generateUniqueId } from '@/utils/codeParser'
|
||||
import { Check, Code, Loader, MousePointer, Save, Settings, X } from 'lucide-react'
|
||||
import { FaCheck, FaCode, FaSpinner, FaMousePointer, FaSave, FaCog, FaTimes } from 'react-icons/fa'
|
||||
|
||||
interface CodeEditorProps {
|
||||
code: string
|
||||
|
|
@ -427,9 +427,9 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
className="px-3 py-2 bg-gray-700 text-gray-300 rounded-lg text-xs font-medium hover:bg-gray-600 transition-colors flex items-center gap-2 disabled:opacity-50"
|
||||
>
|
||||
{isFormatting ? (
|
||||
<Loader className="w-4 h-4 animate-spin" />
|
||||
<FaSpinner className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<Code className="w-4 h-4" />
|
||||
<FaCode className="w-4 h-4" />
|
||||
)}
|
||||
Formatla
|
||||
</button>
|
||||
|
|
@ -442,7 +442,7 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
: 'bg-gray-700 text-gray-300 hover:bg-gray-600'
|
||||
}`}
|
||||
>
|
||||
<Settings className="w-4 h-4" />
|
||||
<FaCog className="w-4 h-4" />
|
||||
Ayarlar
|
||||
</button>
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
onClick={handleResetChanges}
|
||||
className="px-3 py-2 bg-red-600 text-white rounded-lg text-xs font-medium hover:bg-red-700 transition-colors flex items-center gap-2"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<FaTimes className="w-4 h-4" />
|
||||
Sıfırla
|
||||
</button>
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
onClick={handleApplyChanges}
|
||||
className="px-3 py-2 bg-green-600 text-white rounded-lg text-xs font-medium hover:bg-green-700 transition-colors flex items-center gap-2"
|
||||
>
|
||||
<Check className="w-4 h-4" />
|
||||
<FaCheck className="w-4 h-4" />
|
||||
Uygula
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -467,7 +467,7 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
onClick={onComponentSave}
|
||||
className="flex items-center gap-2 bg-yellow-600 text-white px-4 py-2 rounded-lg hover:bg-yellow-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
|
||||
>
|
||||
<Save className="w-4 h-4" />
|
||||
<FaSave className="w-4 h-4" />
|
||||
Kaydet
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -622,12 +622,12 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
{hasChanges && <span className="text-orange-400">● Kaydedilmemiş değişiklikler</span>}
|
||||
{showSuccessMessage && (
|
||||
<span className="text-green-400 flex items-center gap-1">
|
||||
<Check className="w-4 h-4" />
|
||||
<FaCheck className="w-4 h-4" />
|
||||
</span>
|
||||
)}
|
||||
{isDragOver && (
|
||||
<span className="text-blue-400 flex items-center gap-1">
|
||||
<MousePointer className="w-4 h-4" />
|
||||
<FaMousePointer className="w-4 h-4" />
|
||||
Bileşeni bırakmaya hazır
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import React, { useMemo, useState } from "react";
|
||||
import { Search, Square } from "lucide-react";
|
||||
import * as Icons from "lucide-react";
|
||||
import { FaSquare } from 'react-icons/fa';
|
||||
import { AiOutlineSearch } from 'react-icons/ai';
|
||||
import { ComponentDefinition, HookInfo, PropertyInfo } from "../../@types/componentInfo";
|
||||
import { getAllComponentDefinitions } from "./data/componentDefinitions";
|
||||
import navigationIcon from "@/configs/navigation-icon.config";
|
||||
|
||||
interface ComponentLibraryProps {
|
||||
onDragStart: (componentDef: ComponentDefinition, e: React.DragEvent) => void;
|
||||
|
|
@ -86,9 +87,8 @@ export const ComponentLibrary: React.FC<ComponentLibraryProps> = ({
|
|||
}))
|
||||
.filter((cat) => cat.components.length > 0);
|
||||
|
||||
const getIcon = (iconName: string) => {
|
||||
const IconComponent = (Icons as any)[iconName];
|
||||
return IconComponent || Square;
|
||||
const getIcon = (iconName: string): React.ComponentType<any> => {
|
||||
return navigationIcon[iconName] || FaSquare;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -96,7 +96,7 @@ export const ComponentLibrary: React.FC<ComponentLibraryProps> = ({
|
|||
{/* Arama kutusu */}
|
||||
<div className="p-4 border-b border-gray-700">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||
<AiOutlineSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search Components..."
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import React from "react";
|
||||
import { Settings, X, PanelTop as Panels, Eye, EyeOff } from "lucide-react";
|
||||
import {
|
||||
FaCog,
|
||||
FaTimes,
|
||||
FaBars,
|
||||
FaEye,
|
||||
FaEyeSlash
|
||||
} from 'react-icons/fa';
|
||||
import { PanelState } from "./data/componentDefinitions";
|
||||
|
||||
interface PanelManagerProps {
|
||||
|
|
@ -19,8 +25,8 @@ export const PanelManager: React.FC<PanelManagerProps> = ({
|
|||
if (!isOpen) return null;
|
||||
|
||||
const paneller = [
|
||||
{ key: "toolbox" as keyof PanelState, label: "Toolbox", icon: Panels },
|
||||
{ key: "properties" as keyof PanelState, label: "Properties", icon: Settings },
|
||||
{ key: "toolbox" as keyof PanelState, label: "Toolbox", icon: FaBars },
|
||||
{ key: "properties" as keyof PanelState, label: "Properties", icon: FaCog },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -28,7 +34,7 @@ export const PanelManager: React.FC<PanelManagerProps> = ({
|
|||
<div className="bg-white rounded-lg shadow-xl w-96 max-w-full mx-4">
|
||||
<div className="flex items-center justify-between p-4 border-b border-gray-200">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Panels className="w-5 h-5 text-blue-600" />
|
||||
<FaBars className="w-5 h-5 text-blue-600" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">Panel Manager</h2>
|
||||
</div>
|
||||
<button
|
||||
|
|
@ -36,7 +42,7 @@ export const PanelManager: React.FC<PanelManagerProps> = ({
|
|||
className="p-1 hover:bg-gray-100 rounded transition-colors"
|
||||
title="Kapat"
|
||||
>
|
||||
<X className="w-5 h-5 text-gray-500" />
|
||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
|
|
@ -54,7 +60,7 @@ export const PanelManager: React.FC<PanelManagerProps> = ({
|
|||
className={`p-1 rounded transition-colors ${panelState[key] ? "text-blue-600 hover:bg-blue-100" : "text-gray-400 hover:bg-gray-200"}`}
|
||||
title={panelState[key] ? "Hide" : "Show"}
|
||||
>
|
||||
{panelState[key] ? <Eye className="w-4 h-4" /> : <EyeOff className="w-4 h-4" />}
|
||||
{panelState[key] ? <FaEye className="w-4 h-4" /> : <FaEyeSlash className="w-4 h-4" />}
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,105 +1,103 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import * as Babel from "@babel/standalone";
|
||||
import axios from "axios";
|
||||
import {
|
||||
Alert,
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
Calendar,
|
||||
Card,
|
||||
Checkbox,
|
||||
ConfigProvider,
|
||||
DatePicker,
|
||||
Dialog,
|
||||
Drawer,
|
||||
Dropdown,
|
||||
FormItem,
|
||||
FormContainer,
|
||||
Input,
|
||||
InputGroup,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Notification,
|
||||
Pagination,
|
||||
Progress,
|
||||
Radio,
|
||||
RangeCalendar,
|
||||
ScrollBar,
|
||||
Segment,
|
||||
Select,
|
||||
Skeleton,
|
||||
Spinner,
|
||||
Steps,
|
||||
Switcher,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
TimeInput,
|
||||
Timeline,
|
||||
toast,
|
||||
Tooltip,
|
||||
Upload,
|
||||
} from "../ui";
|
||||
import { useComponents } from "../../contexts/ComponentContext";
|
||||
import ErrorBoundary from "./ErrorBoundary";
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import * as Babel from '@babel/standalone'
|
||||
import axios from 'axios'
|
||||
import { useComponents } from '../../contexts/ComponentContext'
|
||||
import ErrorBoundary from './ErrorBoundary'
|
||||
import { toast } from '../ui'
|
||||
|
||||
const compileComponent = (code: string, scope: Record<string, any> = {}) => {
|
||||
const transpiled = Babel.transform(code, {
|
||||
filename: "component.tsx",
|
||||
presets: ["typescript", "react"],
|
||||
plugins: ["transform-modules-commonjs"],
|
||||
}).code;
|
||||
filename: 'component.tsx',
|
||||
presets: ['typescript', 'react'],
|
||||
plugins: ['transform-modules-commonjs'],
|
||||
}).code
|
||||
|
||||
const module = { exports: {} };
|
||||
const module = { exports: {} }
|
||||
const require = (moduleName: string) => {
|
||||
if (moduleName === "react") return React;
|
||||
if (moduleName === "axios") return axios;
|
||||
throw new Error(`Modül bulunamadı: ${moduleName}`);
|
||||
};
|
||||
if (moduleName === 'react') return React
|
||||
if (moduleName === 'axios') return axios
|
||||
throw new Error(`Modül bulunamadı: ${moduleName}`)
|
||||
}
|
||||
|
||||
const scopedEval = new Function(
|
||||
"module",
|
||||
"exports",
|
||||
"require",
|
||||
'module',
|
||||
'exports',
|
||||
'require',
|
||||
...Object.keys(scope),
|
||||
transpiled!
|
||||
);
|
||||
transpiled!,
|
||||
)
|
||||
|
||||
scopedEval(module, module.exports, require, ...Object.values(scope));
|
||||
scopedEval(module, module.exports, require, ...Object.values(scope))
|
||||
|
||||
const compiledModule = module.exports as any;
|
||||
return compiledModule.default;
|
||||
};
|
||||
const compiledModule = module.exports as any
|
||||
return compiledModule.default
|
||||
}
|
||||
|
||||
interface DynamicRendererProps {
|
||||
componentName: string;
|
||||
dependencies?: string[];
|
||||
componentName: string
|
||||
dependencies?: string[]
|
||||
}
|
||||
|
||||
const DynamicRenderer: React.FC<DynamicRendererProps> = ({
|
||||
componentName,
|
||||
dependencies: externalDeps,
|
||||
}) => {
|
||||
const [Component, setComponent] = useState<React.ComponentType<any> | null>(
|
||||
null
|
||||
);
|
||||
const { getComponentByName, components } = useComponents();
|
||||
// Lazy load for UI components
|
||||
const Alert = React.lazy(() => import('../ui/Alert'))
|
||||
const Avatar = React.lazy(() => import('../ui/Avatar'))
|
||||
const Badge = React.lazy(() => import('../ui/Badge'))
|
||||
const Button = React.lazy(() => import('../ui/Button'))
|
||||
const Calendar = React.lazy(() => import('../ui/Calendar'))
|
||||
const Card = React.lazy(() => import('../ui/Card'))
|
||||
const Checkbox = React.lazy(() => import('../ui/Checkbox'))
|
||||
const ConfigProvider = React.lazy(() => import('../ui/ConfigProvider'))
|
||||
const DatePicker = React.lazy(() => import('../ui/DatePicker'))
|
||||
const Dialog = React.lazy(() => import('../ui/Dialog'))
|
||||
const Drawer = React.lazy(() => import('../ui/Drawer'))
|
||||
const Dropdown = React.lazy(() => import('../ui/Dropdown'))
|
||||
const FormItem = React.lazy(() => import('../ui/Form/FormItem'))
|
||||
const FormContainer = React.lazy(() => import('../ui/Form/FormContainer'))
|
||||
const Input = React.lazy(() => import('../ui/Input'))
|
||||
const InputGroup = React.lazy(() => import('../ui/InputGroup'))
|
||||
const Menu = React.lazy(() => import('../ui/Menu'))
|
||||
const MenuItem = React.lazy(() => import('../ui/MenuItem'))
|
||||
const Notification = React.lazy(() => import('../ui/Notification'))
|
||||
const Pagination = React.lazy(() => import('../ui/Pagination'))
|
||||
const Progress = React.lazy(() => import('../ui/Progress'))
|
||||
const Radio = React.lazy(() => import('../ui/Radio'))
|
||||
const RangeCalendar = React.lazy(() => import('../ui/RangeCalendar'))
|
||||
const ScrollBar = React.lazy(() => import('../ui/ScrollBar'))
|
||||
const Segment = React.lazy(() => import('../ui/Segment'))
|
||||
const Select = React.lazy(() => import('../ui/Select'))
|
||||
const Skeleton = React.lazy(() => import('../ui/Skeleton'))
|
||||
const Spinner = React.lazy(() => import('../ui/Spinner'))
|
||||
const Steps = React.lazy(() => import('../ui/Steps'))
|
||||
const Switcher = React.lazy(() => import('../ui/Switcher'))
|
||||
const Table = React.lazy(() => import('../ui/Table'))
|
||||
const Tabs = React.lazy(() => import('../ui/Tabs'))
|
||||
const Tag = React.lazy(() => import('../ui/Tag'))
|
||||
const TimeInput = React.lazy(() => import('../ui/TimeInput'))
|
||||
const Timeline = React.lazy(() => import('../ui/Timeline'))
|
||||
const Tooltip = React.lazy(() => import('../ui/Tooltip'))
|
||||
const Upload = React.lazy(() => import('../ui/Upload'))
|
||||
|
||||
const [Component, setComponent] = useState<React.ComponentType<any> | null>(null)
|
||||
const { getComponentByName, components } = useComponents()
|
||||
|
||||
useEffect(() => {
|
||||
setComponent(null);
|
||||
setComponent(null)
|
||||
|
||||
const storedComponent = getComponentByName(componentName);
|
||||
if (!storedComponent) return;
|
||||
const storedComponent = getComponentByName(componentName)
|
||||
if (!storedComponent) return
|
||||
|
||||
const map = new Map(
|
||||
components.map((c) => {
|
||||
// Parse dependencies from JSON string
|
||||
let componentDeps: string[] = [];
|
||||
let componentDeps: string[] = []
|
||||
try {
|
||||
componentDeps = c.dependencies ? JSON.parse(c.dependencies) : [];
|
||||
componentDeps = c.dependencies ? JSON.parse(c.dependencies) : []
|
||||
} catch {
|
||||
componentDeps = [];
|
||||
componentDeps = []
|
||||
}
|
||||
|
||||
return [
|
||||
|
|
@ -109,11 +107,11 @@ const DynamicRenderer: React.FC<DynamicRendererProps> = ({
|
|||
jsx_code: c.code,
|
||||
dependencies: Array.isArray(componentDeps) ? componentDeps : [],
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
]
|
||||
}),
|
||||
)
|
||||
|
||||
const compiled: Record<string, any> = {};
|
||||
const compiled: Record<string, any> = {}
|
||||
|
||||
const staticComponents: Record<string, any> = {
|
||||
Alert,
|
||||
|
|
@ -154,53 +152,51 @@ const DynamicRenderer: React.FC<DynamicRendererProps> = ({
|
|||
toast,
|
||||
Tooltip,
|
||||
Upload,
|
||||
};
|
||||
}
|
||||
|
||||
const compileWithDependencies = (name: string): any => {
|
||||
if (compiled[name]) return compiled[name];
|
||||
if (compiled[name]) return compiled[name]
|
||||
|
||||
const entry = map.get(name);
|
||||
const entry = map.get(name)
|
||||
if (!entry && staticComponents[name]) {
|
||||
compiled[name] = staticComponents[name];
|
||||
return staticComponents[name];
|
||||
compiled[name] = staticComponents[name]
|
||||
return staticComponents[name]
|
||||
}
|
||||
if (!entry) throw new Error(`Component ${name} not found`);
|
||||
if (!entry) throw new Error(`Component ${name} not found`)
|
||||
|
||||
const depNames =
|
||||
name === componentName && externalDeps
|
||||
? externalDeps
|
||||
: entry.dependencies || [];
|
||||
name === componentName && externalDeps ? externalDeps : entry.dependencies || []
|
||||
|
||||
const deps: Record<string, any> = {};
|
||||
const deps: Record<string, any> = {}
|
||||
for (const dep of depNames) {
|
||||
deps[dep] = compileWithDependencies(dep);
|
||||
deps[dep] = compileWithDependencies(dep)
|
||||
}
|
||||
|
||||
const comp = compileComponent(entry.jsx_code, {
|
||||
React,
|
||||
...staticComponents,
|
||||
...deps,
|
||||
});
|
||||
compiled[name] = comp;
|
||||
})
|
||||
compiled[name] = comp
|
||||
|
||||
return comp;
|
||||
};
|
||||
return comp
|
||||
}
|
||||
|
||||
try {
|
||||
const RootComponent = compileWithDependencies(componentName);
|
||||
setComponent(() => RootComponent);
|
||||
const RootComponent = compileWithDependencies(componentName)
|
||||
setComponent(() => RootComponent)
|
||||
} catch (err: any) {
|
||||
console.error("Compilation error:", err);
|
||||
console.error('Compilation error:', err)
|
||||
}
|
||||
}, [componentName, externalDeps, components, getComponentByName]);
|
||||
}, [componentName, externalDeps, components, getComponentByName])
|
||||
|
||||
if (!Component) return <div>Yükleniyor...</div>;
|
||||
if (!Component) return <div>Yükleniyor...</div>
|
||||
|
||||
return (
|
||||
<ErrorBoundary key={componentName}>
|
||||
<Component />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default DynamicRenderer;
|
||||
export default DynamicRenderer
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@ import React, { useState } from 'react'
|
|||
import { useEntities } from '../../contexts/EntityContext'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
Book,
|
||||
Search,
|
||||
Filter,
|
||||
Globe,
|
||||
Copy,
|
||||
CheckCircle,
|
||||
AlertCircle,
|
||||
Database,
|
||||
Loader2,
|
||||
Send,
|
||||
PlusCircle,
|
||||
Edit3,
|
||||
Trash2,
|
||||
} from 'lucide-react'
|
||||
FaBook,
|
||||
FaSearch,
|
||||
FaFilter,
|
||||
FaGlobe,
|
||||
FaCopy,
|
||||
FaCheckCircle,
|
||||
FaExclamationCircle,
|
||||
FaDatabase,
|
||||
FaSyncAlt,
|
||||
FaPaperPlane,
|
||||
FaPlusCircle,
|
||||
FaEdit,
|
||||
FaTrash
|
||||
} from 'react-icons/fa';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
interface EndpointType {
|
||||
|
|
@ -378,7 +378,7 @@ const ApiManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-2 bg-blue-100 text-blue-700 px-3 py-1 rounded-full text-sm font-medium">
|
||||
<Globe className="w-4 h-4" />
|
||||
<FaGlobe className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Endpoint.SwaggerCompatible')}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -397,7 +397,7 @@ const ApiManager: React.FC = () => {
|
|||
</p>
|
||||
</div>
|
||||
<div className="bg-emerald-100 text-emerald-600 p-3 rounded-lg">
|
||||
<Database className="w-6 h-6" />
|
||||
<FaDatabase className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -410,7 +410,7 @@ const ApiManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.byMethod.GET}</p>
|
||||
</div>
|
||||
<div className="bg-blue-100 text-blue-600 p-3 rounded-lg">
|
||||
<Book className="w-6 h-6" />
|
||||
<FaBook className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -423,7 +423,7 @@ const ApiManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.byMethod.POST}</p>
|
||||
</div>
|
||||
<div className="bg-purple-100 text-purple-600 p-3 rounded-lg">
|
||||
<PlusCircle className="w-6 h-6" />
|
||||
<FaPlusCircle className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -436,7 +436,7 @@ const ApiManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.byMethod.PUT}</p>
|
||||
</div>
|
||||
<div className="bg-purple-100 text-purple-600 p-3 rounded-lg">
|
||||
<Edit3 className="w-6 h-6" />
|
||||
<FaEdit className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -449,7 +449,7 @@ const ApiManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.byMethod.DELETE}</p>
|
||||
</div>
|
||||
<div className="bg-purple-100 text-purple-600 p-3 rounded-lg">
|
||||
<Trash2 className="w-6 h-6" />
|
||||
<FaTrash className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -459,7 +459,7 @@ const ApiManager: React.FC = () => {
|
|||
<div className="bg-white rounded-lg border border-slate-200 p-6 mb-6 shadow-sm">
|
||||
<div className="flex flex-col lg:flex-row gap-4">
|
||||
<div className="flex-1 relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder={translate('::App.DeveloperKit.Endpoint.SearchPlaceholder')}
|
||||
|
|
@ -470,7 +470,7 @@ const ApiManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="w-5 h-5 text-slate-500" />
|
||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||
<select
|
||||
value={filterMethod}
|
||||
onChange={(e) =>
|
||||
|
|
@ -531,7 +531,7 @@ const ApiManager: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="w-5 h-5 text-green-500" />
|
||||
<FaCheckCircle className="w-5 h-5 text-green-500" />
|
||||
<span className="text-sm text-slate-500">{translate('::App.DeveloperKit.Endpoint.Active')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -561,7 +561,7 @@ const ApiManager: React.FC = () => {
|
|||
className="p-2 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
title={translate('::App.DeveloperKit.Endpoint.CopyUrl')}
|
||||
>
|
||||
<Copy className="w-4 h-4" />
|
||||
<FaCopy className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -636,7 +636,7 @@ const ApiManager: React.FC = () => {
|
|||
className="absolute top-2 right-2 p-1 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
title={translate('::App.DeveloperKit.Endpoint.CopyRequestBody')}
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
<FaCopy className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -665,7 +665,7 @@ const ApiManager: React.FC = () => {
|
|||
className="absolute top-2 right-2 p-1 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
title={translate('::App.DeveloperKit.Endpoint.CopyResponse')}
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
<FaCopy className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -680,9 +680,9 @@ const ApiManager: React.FC = () => {
|
|||
className="flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 disabled:bg-blue-400 disabled:cursor-not-allowed transition-colors text-sm font-medium"
|
||||
>
|
||||
{loadingEndpoints.has(endpoint.id) ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
<FaSyncAlt className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<Send className="w-4 h-4" />
|
||||
<FaPaperPlane className="w-4 h-4" />
|
||||
)}
|
||||
{loadingEndpoints.has(endpoint.id) ? translate('::App.DeveloperKit.Endpoint.SendLoading') : translate('::App.DeveloperKit.Endpoint.SendRequest')}
|
||||
</button>
|
||||
|
|
@ -711,9 +711,9 @@ const ApiManager: React.FC = () => {
|
|||
<div className="mt-6 p-4 bg-slate-100 rounded-lg">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
{testResults[endpoint.id].success ? (
|
||||
<CheckCircle className="w-5 h-5 text-green-500" />
|
||||
<FaCheckCircle className="w-5 h-5 text-green-500" />
|
||||
) : (
|
||||
<AlertCircle className="w-5 h-5 text-red-500" />
|
||||
<FaExclamationCircle className="w-5 h-5 text-red-500" />
|
||||
)}
|
||||
<h5 className="font-semibold text-slate-900">
|
||||
{translate('::App.DeveloperKit.Endpoint.TestResultLabel')} ({testResults[endpoint.id].status})
|
||||
|
|
@ -748,7 +748,7 @@ const ApiManager: React.FC = () => {
|
|||
className="absolute top-2 right-2 p-1 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
title={translate('::App.DeveloperKit.Endpoint.CopyResult')}
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
<FaCopy className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -762,7 +762,7 @@ const ApiManager: React.FC = () => {
|
|||
<div className="text-center py-12">
|
||||
<div className="max-w-md mx-auto">
|
||||
<div className="bg-slate-100 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<Book className="w-8 h-8 text-slate-500" />
|
||||
<FaBook className="w-8 h-8 text-slate-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-slate-900 mb-2">
|
||||
{searchTerm || filterMethod !== 'all'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { PanelTop as Panels } from 'lucide-react'
|
||||
import { FaThLarge } from 'react-icons/fa';
|
||||
import {
|
||||
parseReactCode,
|
||||
updateComponentProp,
|
||||
|
|
@ -622,7 +622,7 @@ function CodeLayout() {
|
|||
className="flex items-center space-x-2 px-3 py-2 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
|
||||
title="Panel Manager"
|
||||
>
|
||||
<Panels className="w-4 h-4 text-gray-600" />
|
||||
<FaThLarge className="w-4 h-4 text-gray-600" />
|
||||
<span className="text-sm text-gray-600">Panels</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect, useCallback } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { useComponents } from '../../contexts/ComponentContext'
|
||||
import { Save, ArrowLeft, AlertCircle, RefreshCw } from 'lucide-react'
|
||||
import { FaRegSave, FaArrowLeft, FaExclamationCircle, FaSync } from 'react-icons/fa';
|
||||
import { parseReactCode } from '../../utils/codeParser'
|
||||
import ComponentPreview from '../../components/componentEditor/ComponentPreview'
|
||||
import { EditorState } from '../../@types/componentInfo'
|
||||
|
|
@ -143,7 +143,7 @@ const ComponentEditor: React.FC = () => {
|
|||
return (
|
||||
<div className="h-screen flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<RefreshCw className="w-8 h-8 text-blue-500 animate-spin mx-auto mb-3" />
|
||||
<FaSync className="w-8 h-8 text-blue-500 animate-spin mx-auto mb-3" />
|
||||
<p className="text-slate-600">
|
||||
{translate('::App.DeveloperKit.ComponentEditor.Loading')}
|
||||
</p>
|
||||
|
|
@ -162,7 +162,7 @@ const ComponentEditor: React.FC = () => {
|
|||
onClick={() => navigate(ROUTES_ENUM.protected.saas.developerKitComponents)}
|
||||
className="flex items-center gap-2 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
<FaArrowLeft className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.ComponentEditor.Back')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -221,7 +221,7 @@ const ComponentEditor: React.FC = () => {
|
|||
disabled={isSaving || !name.trim()}
|
||||
className="flex items-center gap-2 bg-yellow-600 text-white px-4 py-2 rounded-lg hover:bg-yellow-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
|
||||
>
|
||||
<Save className="w-4 h-4" />
|
||||
<FaRegSave className="w-4 h-4" />
|
||||
{isSaving
|
||||
? translate('::App.DeveloperKit.ComponentEditor.Saving')
|
||||
: translate('::App.DeveloperKit.ComponentEditor.Save')}
|
||||
|
|
@ -237,7 +237,7 @@ const ComponentEditor: React.FC = () => {
|
|||
<div className="mb-4 bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="bg-red-100 rounded p-1">
|
||||
<AlertCircle className="w-4 h-4 text-red-600" />
|
||||
<FaExclamationCircle className="w-4 h-4 text-red-600" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm text-red-800 font-medium mb-2">
|
||||
|
|
|
|||
|
|
@ -2,19 +2,18 @@ import React, { useState } from 'react'
|
|||
import { Link } from 'react-router-dom'
|
||||
import { useComponents } from '../../contexts/ComponentContext'
|
||||
import {
|
||||
Plus,
|
||||
Search,
|
||||
Edit,
|
||||
Trash2,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Filter,
|
||||
Calendar,
|
||||
Puzzle,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
View,
|
||||
} from 'lucide-react'
|
||||
FaPlus,
|
||||
FaSearch,
|
||||
FaRegEdit,
|
||||
FaTrashAlt,
|
||||
FaEye,
|
||||
FaEyeSlash,
|
||||
FaFilter,
|
||||
FaCalendarAlt,
|
||||
FaPuzzlePiece,
|
||||
FaCheckCircle,
|
||||
FaTimesCircle,
|
||||
} from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
|
|
@ -33,21 +32,21 @@ const ComponentManager: React.FC = () => {
|
|||
{
|
||||
name: translate('::App.DeveloperKit.Component.Total'),
|
||||
value: totalComponents,
|
||||
icon: Puzzle,
|
||||
icon: FaPuzzlePiece,
|
||||
color: 'text-purple-600',
|
||||
bgColor: 'bg-purple-100',
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Component.Active'),
|
||||
value: activeComponents,
|
||||
icon: CheckCircle,
|
||||
icon: FaCheckCircle,
|
||||
color: 'text-emerald-600',
|
||||
bgColor: 'bg-emerald-100',
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Component.Inactive'),
|
||||
value: inactiveComponents,
|
||||
icon: XCircle,
|
||||
icon: FaTimesCircle,
|
||||
color: 'text-slate-600',
|
||||
bgColor: 'bg-slate-100',
|
||||
},
|
||||
|
|
@ -100,7 +99,7 @@ const ComponentManager: React.FC = () => {
|
|||
to={ROUTES_ENUM.protected.saas.developerKitComponentsNew}
|
||||
className="flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Component.New')}
|
||||
</Link>
|
||||
</div>
|
||||
|
|
@ -126,7 +125,7 @@ const ComponentManager: React.FC = () => {
|
|||
<div className="bg-white rounded-lg border border-slate-200 p-6 mb-6">
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<div className="flex-1 relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder={translate('::App.DeveloperKit.Component.SearchPlaceholder')}
|
||||
|
|
@ -136,7 +135,7 @@ const ComponentManager: React.FC = () => {
|
|||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="w-5 h-5 text-slate-500" />
|
||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||
<select
|
||||
value={filterActive}
|
||||
onChange={(e) => setFilterActive(e.target.value as 'all' | 'active' | 'inactive')}
|
||||
|
|
@ -195,7 +194,7 @@ const ComponentManager: React.FC = () => {
|
|||
)}
|
||||
<div className="flex items-center gap-4 text-xs text-slate-500">
|
||||
<div className="flex items-center gap-1">
|
||||
<Calendar className="w-3 h-3" />
|
||||
<FaCalendarAlt className="w-3 h-3" />
|
||||
<span>
|
||||
{component.lastModificationTime
|
||||
? new Date(component.lastModificationTime).toLocaleDateString()
|
||||
|
|
@ -231,12 +230,12 @@ const ComponentManager: React.FC = () => {
|
|||
>
|
||||
{component.isActive ? (
|
||||
<>
|
||||
<Eye className="w-3 h-3" />
|
||||
<FaEye className="w-3 h-3" />
|
||||
{translate('::App.DeveloperKit.Component.Active')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<EyeOff className="w-3 h-3" />
|
||||
<FaEyeSlash className="w-3 h-3" />
|
||||
{translate('::App.DeveloperKit.Component.Inactive')}
|
||||
</>
|
||||
)}
|
||||
|
|
@ -252,7 +251,7 @@ const ComponentManager: React.FC = () => {
|
|||
className="p-2 text-slate-600 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.Component.Edit')}
|
||||
>
|
||||
<Edit className="w-4 h-4" />
|
||||
<FaRegEdit className="w-4 h-4" />
|
||||
</Link>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitComponentsView.replace(
|
||||
|
|
@ -262,14 +261,14 @@ const ComponentManager: React.FC = () => {
|
|||
className="p-2 text-slate-600 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.Component.View')}
|
||||
>
|
||||
<View className="w-4 h-4" />
|
||||
<FaEye className="w-4 h-4" />
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => handleDelete(component.id, component.name)}
|
||||
className="p-2 text-slate-600 hover:text-red-600 hover:bg-red-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.Component.Delete')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -281,7 +280,7 @@ const ComponentManager: React.FC = () => {
|
|||
<div className="text-center py-12">
|
||||
<div className="max-w-md mx-auto">
|
||||
<div className="bg-slate-100 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<Plus className="w-8 h-8 text-slate-500" />
|
||||
<FaPlus className="w-8 h-8 text-slate-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-slate-900 mb-2">
|
||||
{searchTerm || filterActive !== 'all'
|
||||
|
|
@ -298,7 +297,7 @@ const ComponentManager: React.FC = () => {
|
|||
to={ROUTES_ENUM.protected.saas.developerKitComponentsNew}
|
||||
className="inline-flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Component.Empty.Initial.Action')}
|
||||
</Link>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@ import { useComponents } from "../../contexts/ComponentContext";
|
|||
import { useEntities } from "../../contexts/EntityContext";
|
||||
import { useSystemHealth } from "../../utils/hooks/useDeveloperKit";
|
||||
import {
|
||||
Database,
|
||||
Zap,
|
||||
Server,
|
||||
Puzzle,
|
||||
Activity,
|
||||
Code,
|
||||
CheckCircle,
|
||||
ArrowRight,
|
||||
AlertCircle,
|
||||
Wifi,
|
||||
WifiOff,
|
||||
} from "lucide-react";
|
||||
FaDatabase,
|
||||
FaBolt,
|
||||
FaServer,
|
||||
FaPuzzlePiece,
|
||||
FaCog,
|
||||
FaChartLine,
|
||||
FaCode,
|
||||
FaCheckCircle,
|
||||
FaArrowRight,
|
||||
FaExclamationCircle,
|
||||
FaWifi,
|
||||
FaWindowClose
|
||||
} from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from "@/routes/route.constant";
|
||||
import { useLocalization } from "@/utils/hooks/useLocalization";
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ const Dashboard: React.FC = () => {
|
|||
name: translate('::App.DeveloperKit.Dashboard.Stats.Entities'),
|
||||
value: entities.filter((e) => e.isActive).length,
|
||||
total: entities.length,
|
||||
icon: Database,
|
||||
icon: FaDatabase,
|
||||
color: "text-blue-600",
|
||||
bgColor: "bg-blue-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEntities,
|
||||
|
|
@ -39,7 +40,7 @@ const Dashboard: React.FC = () => {
|
|||
name: translate('::App.DeveloperKit.Dashboard.Stats.Migrations'),
|
||||
value: migrations.filter((m) => m.status === "pending").length,
|
||||
total: migrations.length,
|
||||
icon: Zap,
|
||||
icon: FaBolt,
|
||||
color: "text-yellow-600",
|
||||
bgColor: "bg-yellow-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
|
|
@ -48,7 +49,7 @@ const Dashboard: React.FC = () => {
|
|||
name: translate('::App.DeveloperKit.Dashboard.Stats.APIs'),
|
||||
value: generatedEndpoints.filter((e) => e.isActive).length,
|
||||
total: generatedEndpoints.length,
|
||||
icon: Server,
|
||||
icon: FaServer,
|
||||
color: "text-emerald-600",
|
||||
bgColor: "bg-emerald-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEndpoints,
|
||||
|
|
@ -57,7 +58,7 @@ const Dashboard: React.FC = () => {
|
|||
name: translate('::App.DeveloperKit.Dashboard.Stats.Components'),
|
||||
value: components?.filter((c) => c.isActive).length,
|
||||
total: components?.length,
|
||||
icon: Puzzle,
|
||||
icon: FaPuzzlePiece,
|
||||
color: "text-purple-600",
|
||||
bgColor: "bg-purple-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitComponents,
|
||||
|
|
@ -69,7 +70,7 @@ const Dashboard: React.FC = () => {
|
|||
step: 1,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.CreateEntity'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.CreateEntity.Desc'),
|
||||
icon: Database,
|
||||
icon: FaDatabase,
|
||||
color: "bg-blue-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEntitiesNew,
|
||||
status: "ready",
|
||||
|
|
@ -78,7 +79,7 @@ const Dashboard: React.FC = () => {
|
|||
step: 2,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.GenerateMigration'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.GenerateMigration.Desc'),
|
||||
icon: Zap,
|
||||
icon: FaBolt,
|
||||
color: "bg-yellow-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
status: entities.some((e) => e.migrationStatus === "pending")
|
||||
|
|
@ -89,7 +90,7 @@ const Dashboard: React.FC = () => {
|
|||
step: 3,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.ApplyMigration'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.ApplyMigration.Desc'),
|
||||
icon: CheckCircle,
|
||||
icon: FaCheckCircle,
|
||||
color: "bg-green-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
status: migrations.some((m) => m.status === "pending")
|
||||
|
|
@ -100,7 +101,7 @@ const Dashboard: React.FC = () => {
|
|||
step: 4,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.GenerateAPI'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.GenerateAPI.Desc'),
|
||||
icon: Server,
|
||||
icon: FaServer,
|
||||
color: "bg-emerald-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEndpoints,
|
||||
status: "ready",
|
||||
|
|
@ -109,7 +110,7 @@ const Dashboard: React.FC = () => {
|
|||
step: 5,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.BuildComponent'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.BuildComponent.Desc'),
|
||||
icon: Puzzle,
|
||||
icon: FaPuzzlePiece,
|
||||
color: "bg-purple-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitComponentsNew,
|
||||
status: "ready",
|
||||
|
|
@ -132,23 +133,23 @@ const Dashboard: React.FC = () => {
|
|||
].slice(0, 3);
|
||||
|
||||
const systemHealth = [
|
||||
{ name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Frontend'), status: translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy'), icon: Code },
|
||||
{ name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Frontend'), status: translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy'), icon: FaCode },
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Backend'),
|
||||
status: isOnline ? translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy') : translate('::App.DeveloperKit.Dashboard.SystemHealth.Offline'),
|
||||
icon: Server,
|
||||
icon: FaServer,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Database'),
|
||||
status: isOnline ? translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy') : translate('::App.DeveloperKit.Dashboard.SystemHealth.Unknown'),
|
||||
icon: Database,
|
||||
icon: FaDatabase,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Migrations'),
|
||||
status: migrations.some((m) => m.status === "failed")
|
||||
? translate('::App.DeveloperKit.Dashboard.SystemHealth.Warning')
|
||||
: translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy'),
|
||||
icon: Zap,
|
||||
icon: FaBolt,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -183,12 +184,12 @@ const Dashboard: React.FC = () => {
|
|||
/>
|
||||
{isOnline ? (
|
||||
<>
|
||||
<Wifi className="w-4 h-4" />
|
||||
<FaWifi className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Dashboard.SystemHealth.Online')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<WifiOff className="w-4 h-4" />
|
||||
<FaWindowClose className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Dashboard.SystemHealth.OfflineStatus')}
|
||||
</>
|
||||
)}
|
||||
|
|
@ -212,7 +213,7 @@ const Dashboard: React.FC = () => {
|
|||
>
|
||||
<Icon className="w-6 h-6" />
|
||||
</div>
|
||||
<ArrowRight className="w-4 h-4 text-slate-400 group-hover:text-slate-600 transition-colors" />
|
||||
<FaArrowRight className="w-4 h-4 text-slate-400 group-hover:text-slate-600 transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
|
|
@ -233,7 +234,7 @@ const Dashboard: React.FC = () => {
|
|||
{/* Development Flow */}
|
||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-8">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<Activity className="w-6 h-6 text-blue-600" />
|
||||
<FaCog className="w-6 h-6 text-blue-600" />
|
||||
<h2 className="text-xl font-semibold text-slate-900">
|
||||
{translate('::App.DeveloperKit.Dashboard.Flow.Title')}
|
||||
</h2>
|
||||
|
|
@ -260,7 +261,7 @@ const Dashboard: React.FC = () => {
|
|||
{flow.status === "action-needed" && (
|
||||
<div className="absolute -top-2 -right-2">
|
||||
<div className="bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center">
|
||||
<AlertCircle className="w-4 h-4" />
|
||||
<FaExclamationCircle className="w-4 h-4" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -268,7 +269,7 @@ const Dashboard: React.FC = () => {
|
|||
|
||||
{index < developmentFlow.length - 1 && (
|
||||
<div className="hidden lg:block absolute top-1/2 -right-3 transform -translate-y-1/2">
|
||||
<ArrowRight className="w-6 h-6 text-slate-300" />
|
||||
<FaArrowRight className="w-6 h-6 text-slate-300" />
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
|
|
@ -281,7 +282,7 @@ const Dashboard: React.FC = () => {
|
|||
{/* System Health */}
|
||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Activity className="w-5 h-5 text-green-500" />
|
||||
<FaCog className="w-5 h-5 text-green-500" />
|
||||
<h3 className="text-lg font-semibold text-slate-900">
|
||||
{translate('::App.DeveloperKit.Dashboard.SystemHealth.Title') }
|
||||
</h3>
|
||||
|
|
@ -374,14 +375,14 @@ const Dashboard: React.FC = () => {
|
|||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesEdit.replace(':id', entity.id)}
|
||||
className="text-blue-600 hover:text-blue-700"
|
||||
>
|
||||
<Database className="w-4 h-4" />
|
||||
<FaDatabase className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-8">
|
||||
<Database className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<FaDatabase className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<p className="text-slate-500 mb-2">{translate('::App.DeveloperKit.Dashboard.Empty.Entity')}</p>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
|
|
@ -437,14 +438,14 @@ const Dashboard: React.FC = () => {
|
|||
to={ROUTES_ENUM.protected.saas.developerKitMigrations}
|
||||
className="text-yellow-600 hover:text-yellow-700"
|
||||
>
|
||||
<Zap className="w-4 h-4" />
|
||||
<FaBolt className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-8">
|
||||
<Zap className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<FaBolt className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<p className="text-slate-500 mb-2">{translate('::App.DeveloperKit.Dashboard.Empty.Migration')}</p>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
|
|
@ -508,14 +509,14 @@ const Dashboard: React.FC = () => {
|
|||
to="/docs"
|
||||
className="text-emerald-600 hover:text-emerald-700"
|
||||
>
|
||||
<Server className="w-4 h-4" />
|
||||
<FaServer className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-8">
|
||||
<Server className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<FaServer className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<p className="text-slate-500 mb-2">{translate('::App.DeveloperKit.Dashboard.Empty.Endpoint')}</p>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEndpointsNew}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { useEntities, EntityFieldType } from '../../contexts/EntityContext'
|
||||
import { Save, ArrowLeft, Plus, Trash2, Database, HelpCircle } from 'lucide-react'
|
||||
import {
|
||||
FaSave,
|
||||
FaArrowLeft,
|
||||
FaPlus,
|
||||
FaTrashAlt,
|
||||
FaDatabase,
|
||||
FaQuestionCircle
|
||||
} from 'react-icons/fa';
|
||||
import { CreateUpdateCustomEntityFieldDto, CustomEntityField } from '@/proxy/developerKit/models'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -172,12 +179,12 @@ const EntityEditor: React.FC = () => {
|
|||
onClick={() => navigate(ROUTES_ENUM.protected.saas.developerKitEntities)}
|
||||
className="flex items-center gap-2 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
<FaArrowLeft className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.EntityEditor.Back')}
|
||||
</button>
|
||||
<div className="h-6 w-px bg-slate-300" />
|
||||
<div className="flex items-center gap-2">
|
||||
<Database className="w-6 h-6 text-blue-600" />
|
||||
<FaDatabase className="w-6 h-6 text-blue-600" />
|
||||
<h1 className="text-xl font-semibold text-slate-900">
|
||||
{isEditing
|
||||
? translate('::App.DeveloperKit.EntityEditor.Title.Edit')
|
||||
|
|
@ -189,12 +196,12 @@ const EntityEditor: React.FC = () => {
|
|||
{/* Help Tooltip */}
|
||||
<div className="relative group">
|
||||
<button className="p-2 text-slate-400 hover:text-slate-600 transition-colors">
|
||||
<HelpCircle className="w-4 h-4" />
|
||||
<FaQuestionCircle className="w-4 h-4" />
|
||||
</button>
|
||||
<div className="absolute right-0 top-full mt-2 w-96 bg-slate-900 text-white text-sm rounded-lg p-4 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50 shadow-xl">
|
||||
<div className="absolute -top-1 right-4 w-2 h-2 bg-slate-900 rotate-45"></div>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Database className="w-4 h-4 text-blue-400" />
|
||||
<FaDatabase className="w-4 h-4 text-blue-400" />
|
||||
<h4 className="font-semibold text-blue-200">{translate('::App.DeveloperKit.EntityEditor.Tooltip.Title')}</h4>
|
||||
</div>
|
||||
<p className="text-slate-300 leading-relaxed">
|
||||
|
|
@ -208,7 +215,7 @@ const EntityEditor: React.FC = () => {
|
|||
disabled={isSaving || !name.trim() || !displayName.trim() || !tableName.trim()}
|
||||
className="flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
|
||||
>
|
||||
<Save className="w-4 h-4" />
|
||||
<FaSave className="w-4 h-4" />
|
||||
{isSaving ? translate('::App.DeveloperKit.EntityEditor.Saving') : translate('::App.DeveloperKit.EntityEditor.Save')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -370,7 +377,7 @@ const EntityEditor: React.FC = () => {
|
|||
onClick={addField}
|
||||
className="flex items-center gap-2 bg-blue-600 text-white px-3 py-2 rounded-lg hover:bg-blue-700 transition-colors text-sm"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.EntityEditor.AddField')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -484,7 +491,7 @@ const EntityEditor: React.FC = () => {
|
|||
className="p-2 text-slate-600 hover:text-red-600 hover:bg-red-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.EntityEditor.RemoveField')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -494,7 +501,7 @@ const EntityEditor: React.FC = () => {
|
|||
|
||||
{fields.length === 0 && (
|
||||
<div className="text-center py-8 text-slate-500">
|
||||
<Database className="w-12 h-12 mx-auto mb-2 text-slate-300" />
|
||||
<FaDatabase className="w-12 h-12 mx-auto mb-2 text-slate-300" />
|
||||
<p>{translate('::App.DeveloperKit.EntityEditor.NoFields')}</p>
|
||||
<p className="text-sm">{translate('::App.DeveloperKit.EntityEditor.NoFieldsDescription')}</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useEntities } from '../../contexts/EntityContext';
|
||||
import {
|
||||
Plus,
|
||||
Search,
|
||||
Edit,
|
||||
Trash2,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Filter,
|
||||
Calendar,
|
||||
Database,
|
||||
CheckCircle,
|
||||
Table,
|
||||
Zap
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
FaPlus,
|
||||
FaSearch,
|
||||
FaEdit,
|
||||
FaTrashAlt,
|
||||
FaEye,
|
||||
FaEyeSlash,
|
||||
FaFilter,
|
||||
FaCalendarAlt,
|
||||
FaDatabase,
|
||||
FaCheckCircle,
|
||||
FaTable,
|
||||
FaBolt
|
||||
} from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization';
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ const EntityManager: React.FC = () => {
|
|||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
className="flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors shadow-sm hover:shadow-md"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Entity.NewEntity')}
|
||||
</Link>
|
||||
</div>
|
||||
|
|
@ -89,7 +89,7 @@ const EntityManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.total}</p>
|
||||
</div>
|
||||
<div className="bg-blue-100 text-blue-600 p-3 rounded-lg">
|
||||
<Database className="w-6 h-6" />
|
||||
<FaDatabase className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -105,7 +105,7 @@ const EntityManager: React.FC = () => {
|
|||
</p>
|
||||
</div>
|
||||
<div className="bg-green-100 text-green-600 p-3 rounded-lg">
|
||||
<CheckCircle className="w-6 h-6" />
|
||||
<FaCheckCircle className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -116,7 +116,7 @@ const EntityManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.migrationsPending}</p>
|
||||
</div>
|
||||
<div className="bg-purple-100 text-purple-600 p-3 rounded-lg">
|
||||
<Zap className="w-6 h-6" />
|
||||
<FaBolt className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -127,7 +127,7 @@ const EntityManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.endpointsApplied}</p>
|
||||
</div>
|
||||
<div className="bg-emerald-100 text-emerald-600 p-3 rounded-lg">
|
||||
<Zap className="w-6 h-6" />
|
||||
<FaBolt className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -137,7 +137,7 @@ const EntityManager: React.FC = () => {
|
|||
<div className="bg-white rounded-lg border border-slate-200 p-6 mb-6 shadow-sm">
|
||||
<div className="flex flex-col lg:flex-row gap-4">
|
||||
<div className="flex-1 relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder={translate('::App.DeveloperKit.Entity.SearchPlaceholder')}
|
||||
|
|
@ -148,7 +148,7 @@ const EntityManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="w-5 h-5 text-slate-500" />
|
||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||
<select
|
||||
value={filterActive}
|
||||
onChange={(e) => setFilterActive(e.target.value as 'all' | 'active' | 'inactive')}
|
||||
|
|
@ -174,7 +174,7 @@ const EntityManager: React.FC = () => {
|
|||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="bg-blue-100 text-blue-600 p-2 rounded-lg">
|
||||
<Table className="w-5 h-5" />
|
||||
<FaTable className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-slate-900">
|
||||
|
|
@ -191,13 +191,13 @@ const EntityManager: React.FC = () => {
|
|||
)}
|
||||
<div className="flex items-center gap-4 text-xs text-slate-500 mb-3">
|
||||
<div className="flex items-center gap-1">
|
||||
<Calendar className="w-3 h-3" />
|
||||
<FaCalendarAlt className="w-3 h-3" />
|
||||
<span>
|
||||
{translate('::App.DeveloperKit.Entity.Updated')}: {entity.lastModificationTime ? new Date(entity.lastModificationTime).toLocaleDateString() : 'Never'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Database className="w-3 h-3" />
|
||||
<FaDatabase className="w-3 h-3" />
|
||||
<span>{entity.fields.length} {translate('::App.DeveloperKit.Entity.Fields')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -270,12 +270,12 @@ const EntityManager: React.FC = () => {
|
|||
>
|
||||
{entity.isActive ? (
|
||||
<>
|
||||
<Eye className="w-3 h-3" />
|
||||
<FaEye className="w-3 h-3" />
|
||||
{translate('::App.DeveloperKit.Entity.Active')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<EyeOff className="w-3 h-3" />
|
||||
<FaEyeSlash className="w-3 h-3" />
|
||||
{translate('::App.DeveloperKit.Entity.Inactive')}
|
||||
</>
|
||||
)}
|
||||
|
|
@ -287,14 +287,14 @@ const EntityManager: React.FC = () => {
|
|||
className="p-2 text-slate-600 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.Entity.Edit')}
|
||||
>
|
||||
<Edit className="w-4 h-4" />
|
||||
<FaEdit className="w-4 h-4" />
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => handleDelete(entity.id, entity.displayName)}
|
||||
className="p-2 text-slate-600 hover:text-red-600 hover:bg-red-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.Entity.Delete')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -307,7 +307,7 @@ const EntityManager: React.FC = () => {
|
|||
<div className="text-center py-12">
|
||||
<div className="max-w-md mx-auto">
|
||||
<div className="bg-slate-100 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<Database className="w-8 h-8 text-slate-500" />
|
||||
<FaDatabase className="w-8 h-8 text-slate-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-slate-900 mb-2">
|
||||
{searchTerm || filterActive !== 'all' ? translate('::App.DeveloperKit.Entity.NoEntitiesFound') : translate('::App.DeveloperKit.Entity.NoEntitiesYet')}
|
||||
|
|
@ -323,7 +323,7 @@ const EntityManager: React.FC = () => {
|
|||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
className="inline-flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors shadow-sm hover:shadow-md"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Entity.CreateEntity')}
|
||||
</Link>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@ import React, { useState } from 'react'
|
|||
import { useNavigate } from 'react-router-dom'
|
||||
import { useEntities } from '../../contexts/EntityContext'
|
||||
import {
|
||||
Zap,
|
||||
Search,
|
||||
Filter,
|
||||
Calendar,
|
||||
Database,
|
||||
Play,
|
||||
CheckCircle,
|
||||
AlertCircle,
|
||||
Clock,
|
||||
FileText,
|
||||
Download,
|
||||
Eye,
|
||||
RefreshCw,
|
||||
Trash2,
|
||||
Plus,
|
||||
} from 'lucide-react'
|
||||
FaBolt,
|
||||
FaSearch,
|
||||
FaFilter,
|
||||
FaCalendarAlt,
|
||||
FaDatabase,
|
||||
FaPlay,
|
||||
FaCheckCircle,
|
||||
FaRegBell,
|
||||
FaRegClock,
|
||||
FaRegFileAlt,
|
||||
FaDownload,
|
||||
FaEye,
|
||||
FaSync,
|
||||
FaTrashAlt,
|
||||
FaPlus
|
||||
} from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
|
|
@ -126,13 +126,13 @@ const MigrationManager: React.FC = () => {
|
|||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return Clock
|
||||
return FaRegClock
|
||||
case 'applied':
|
||||
return CheckCircle
|
||||
return FaCheckCircle
|
||||
case 'failed':
|
||||
return AlertCircle
|
||||
return FaRegBell
|
||||
default:
|
||||
return Clock
|
||||
return FaRegClock
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ const MigrationManager: React.FC = () => {
|
|||
{error && (
|
||||
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 text-red-800">
|
||||
<AlertCircle className="w-5 h-5" />
|
||||
<FaRegBell className="w-5 h-5" />
|
||||
<span className="font-medium">Error</span>
|
||||
</div>
|
||||
<p className="text-red-700 text-sm mt-1">{error}</p>
|
||||
|
|
@ -169,12 +169,12 @@ const MigrationManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-2 bg-blue-100 text-blue-700 px-3 py-1 rounded-full text-sm font-medium">
|
||||
<Database className="w-4 h-4" />
|
||||
<FaDatabase className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Migration.SchemaManagement')}
|
||||
</div>
|
||||
{loading && (
|
||||
<div className="flex items-center gap-2 bg-yellow-100 text-yellow-700 px-3 py-1 rounded-full text-sm font-medium">
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
<FaSync className="w-4 h-4 animate-spin" />
|
||||
{translate('::App.DeveloperKit.Migration.Loading')}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -190,7 +190,7 @@ const MigrationManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.total}</p>
|
||||
</div>
|
||||
<div className="bg-blue-100 text-blue-600 p-3 rounded-lg">
|
||||
<FileText className="w-6 h-6" />
|
||||
<FaRegFileAlt className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -201,7 +201,7 @@ const MigrationManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.pending}</p>
|
||||
</div>
|
||||
<div className="bg-yellow-100 text-yellow-600 p-3 rounded-lg">
|
||||
<Clock className="w-6 h-6" />
|
||||
<FaRegClock className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -212,7 +212,7 @@ const MigrationManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.applied}</p>
|
||||
</div>
|
||||
<div className="bg-green-100 text-green-600 p-3 rounded-lg">
|
||||
<CheckCircle className="w-6 h-6" />
|
||||
<FaCheckCircle className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -223,7 +223,7 @@ const MigrationManager: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.failed}</p>
|
||||
</div>
|
||||
<div className="bg-red-100 text-red-600 p-3 rounded-lg">
|
||||
<AlertCircle className="w-6 h-6" />
|
||||
<FaRegBell className="w-6 h-6" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -234,7 +234,7 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-6 mb-6">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="bg-yellow-100 rounded-lg p-2">
|
||||
<Zap className="w-6 h-6 text-yellow-600" />
|
||||
<FaBolt className="w-6 h-6 text-yellow-600" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-2">
|
||||
|
|
@ -271,7 +271,7 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-white rounded-lg border border-slate-200 p-6 mb-6 shadow-sm">
|
||||
<div className="flex flex-col lg:flex-row gap-4">
|
||||
<div className="flex-1 relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder={translate('::App.DeveloperKit.Migration.SearchPlaceholder')}
|
||||
|
|
@ -282,7 +282,7 @@ const MigrationManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="w-5 h-5 text-slate-500" />
|
||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||
<select
|
||||
value={filterStatus}
|
||||
onChange={(e) =>
|
||||
|
|
@ -315,7 +315,7 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="bg-blue-100 text-blue-600 p-2 rounded-lg">
|
||||
<Database className="w-5 h-5" />
|
||||
<FaDatabase className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-slate-900">
|
||||
|
|
@ -332,14 +332,14 @@ const MigrationManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-4 text-xs text-slate-500">
|
||||
<div className="flex items-center gap-1">
|
||||
<Calendar className="w-3 h-3" />
|
||||
<FaCalendarAlt className="w-3 h-3" />
|
||||
<span>
|
||||
{translate('::App.DeveloperKit.Migration.Created')} {new Date(migration.creationTime).toLocaleDateString()}
|
||||
</span>
|
||||
</div>
|
||||
{migration.appliedAt && (
|
||||
<div className="flex items-center gap-1">
|
||||
<CheckCircle className="w-3 h-3" />
|
||||
<FaCheckCircle className="w-3 h-3" />
|
||||
<span>
|
||||
{translate('::App.DeveloperKit.Migration.AppliedLabel')} {new Date(migration.appliedAt).toLocaleDateString()}
|
||||
</span>
|
||||
|
|
@ -364,7 +364,7 @@ const MigrationManager: React.FC = () => {
|
|||
: 'text-orange-600 hover:text-orange-900 hover:bg-orange-50'
|
||||
}`}
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
<FaEye className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Migration.ViewSQL')}
|
||||
{!migration.sqlScript && (
|
||||
<span className="ml-1 text-xs text-orange-500">({translate('::App.DeveloperKit.Migration.NoSQL')})</span>
|
||||
|
|
@ -379,7 +379,7 @@ const MigrationManager: React.FC = () => {
|
|||
: 'text-slate-400 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
<FaDownload className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Migration.Download')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -393,12 +393,12 @@ const MigrationManager: React.FC = () => {
|
|||
>
|
||||
{applyingMigration === migration.id ? (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
<FaSync className="w-4 h-4 animate-spin" />
|
||||
{translate('::App.DeveloperKit.Migration.Applying')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Play className="w-4 h-4" />
|
||||
<FaPlay className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Migration.ApplyMigration')}
|
||||
</>
|
||||
)}
|
||||
|
|
@ -409,9 +409,9 @@ const MigrationManager: React.FC = () => {
|
|||
className="flex items-center gap-2 bg-red-600 text-white px-3 py-2 rounded-lg hover:bg-red-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{deletingMigration === migration.id ? (
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
<FaSync className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
</>
|
||||
|
|
@ -424,12 +424,12 @@ const MigrationManager: React.FC = () => {
|
|||
>
|
||||
{generatingEndpoints === migration.entityId ? (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
<FaSync className="w-4 h-4 animate-spin" />
|
||||
{translate('::App.DeveloperKit.Migration.Generating')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Migration.GenerateCrudEndpoints')}
|
||||
</>
|
||||
)}
|
||||
|
|
@ -451,7 +451,7 @@ const MigrationManager: React.FC = () => {
|
|||
) : (
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 text-yellow-800">
|
||||
<AlertCircle className="w-5 h-5" />
|
||||
<FaRegBell className="w-5 h-5" />
|
||||
<span className="font-medium">{translate('::App.DeveloperKit.Migration.NoSQLScript')}</span>
|
||||
</div>
|
||||
<p className="text-yellow-700 text-sm mt-1">
|
||||
|
|
@ -467,7 +467,7 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="mt-4 pt-4 border-t border-slate-200">
|
||||
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 text-red-800 mb-2">
|
||||
<AlertCircle className="w-5 h-5" />
|
||||
<FaRegBell className="w-5 h-5" />
|
||||
<span className="font-medium">{translate('::App.DeveloperKit.Migration.MigrationFailed')}</span>
|
||||
</div>
|
||||
<p className="text-red-700 text-sm">{migration.errorMessage}</p>
|
||||
|
|
@ -483,7 +483,7 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="text-center py-12">
|
||||
<div className="max-w-md mx-auto">
|
||||
<div className="bg-slate-100 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<Zap className="w-8 h-8 text-slate-500" />
|
||||
<FaBolt className="w-8 h-8 text-slate-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-slate-900 mb-2">
|
||||
{searchTerm || filterStatus !== 'all' ? translate('::App.DeveloperKit.Migration.NoMigrationsFound') : translate('::App.DeveloperKit.Migration.NoMigrationsYet')}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
import React, { useCallback, useState } from 'react'
|
||||
import { Upload, File, X, AlertCircle } from 'lucide-react'
|
||||
import {
|
||||
FaUpload,
|
||||
FaFile,
|
||||
FaTimes,
|
||||
FaRegCircle
|
||||
} from 'react-icons/fa';
|
||||
|
||||
interface FileUploadAreaProps {
|
||||
onFileUpload: (file: File) => void
|
||||
|
|
@ -112,7 +117,7 @@ export const FileUploadArea: React.FC<FileUploadAreaProps> = ({
|
|||
/>
|
||||
|
||||
<div className="text-center">
|
||||
<Upload
|
||||
<FaUpload
|
||||
className={`mx-auto h-3 w-3 ${dragActive ? 'text-blue-500' : 'text-slate-400'}`}
|
||||
/>
|
||||
<div className="text-lg font-medium text-slate-700 mb-2">
|
||||
|
|
@ -128,7 +133,7 @@ export const FileUploadArea: React.FC<FileUploadAreaProps> = ({
|
|||
<div className="border border-slate-200 rounded-lg p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-3 min-w-0 flex-1">
|
||||
<File className="w-8 h-8 text-blue-500 flex-shrink-0" />
|
||||
<FaFile className="w-8 h-8 text-blue-500 flex-shrink-0" />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="font-medium text-slate-800 truncate">{selectedFile.name}</div>
|
||||
<div className="text-sm text-slate-500">{formatFileSize(selectedFile.size)}</div>
|
||||
|
|
@ -138,7 +143,7 @@ export const FileUploadArea: React.FC<FileUploadAreaProps> = ({
|
|||
onClick={clearFile}
|
||||
className="p-2 text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded-lg transition-colors"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<FaTimes className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -146,7 +151,7 @@ export const FileUploadArea: React.FC<FileUploadAreaProps> = ({
|
|||
|
||||
{error && (
|
||||
<div className="flex items-center space-x-2 p-3 bg-red-50 border border-red-200 rounded-lg">
|
||||
<AlertCircle className="w-5 h-5 text-red-500" />
|
||||
<FaRegCircle className="w-5 h-5 text-red-500" />
|
||||
<span className="text-red-700">{error}</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -164,7 +169,7 @@ export const FileUploadArea: React.FC<FileUploadAreaProps> = ({
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<Upload className="w-4 h-4" />
|
||||
<FaUpload className="w-4 h-4" />
|
||||
<span>Upload File</span>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import React, { useState, useEffect, useMemo } from 'react'
|
||||
import {
|
||||
Upload,
|
||||
CheckCircle,
|
||||
AlertCircle,
|
||||
Clock,
|
||||
RefreshCw,
|
||||
Eye,
|
||||
Trash2,
|
||||
Download,
|
||||
FileSpreadsheet,
|
||||
FileText,
|
||||
} from 'lucide-react'
|
||||
FaUpload,
|
||||
FaCheckCircle,
|
||||
FaRegBell,
|
||||
FaClock,
|
||||
FaSync,
|
||||
FaEye,
|
||||
FaTrashAlt,
|
||||
FaDownload,
|
||||
FaFileExcel,
|
||||
FaFileAlt
|
||||
} from 'react-icons/fa';
|
||||
import { FileUploadArea } from './FileUploadArea'
|
||||
import { ImportPreview } from './ImportPreview'
|
||||
import { ImportProgress } from './ImportProgress'
|
||||
|
|
@ -168,14 +168,14 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'uploaded':
|
||||
return <CheckCircle className="w-5 h-5 text-green-500" />
|
||||
return <FaCheckCircle className="w-5 h-5 text-green-500" />
|
||||
case 'failed':
|
||||
return <AlertCircle className="w-5 h-5 text-red-500" />
|
||||
return <FaRegBell className="w-5 h-5 text-red-500" />
|
||||
case 'processing':
|
||||
case 'validating':
|
||||
return <RefreshCw className="w-5 h-5 text-blue-500 animate-spin" />
|
||||
return <FaSync className="w-5 h-5 text-blue-500 animate-spin" />
|
||||
default:
|
||||
return <Clock className="w-5 h-5 text-yellow-500" />
|
||||
return <FaClock className="w-5 h-5 text-yellow-500" />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,9 +233,9 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
: 'text-slate-600 hover:text-slate-800 hover:bg-slate-50'
|
||||
}`}
|
||||
>
|
||||
{tab === 'import' && <Upload className="w-4 h-4" />}
|
||||
{tab === 'preview' && <Eye className="w-4 h-4" />}
|
||||
{tab === 'history' && <Clock className="w-4 h-4" />}
|
||||
{tab === 'import' && <FaUpload className="w-4 h-4" />}
|
||||
{tab === 'preview' && <FaEye className="w-4 h-4" />}
|
||||
{tab === 'history' && <FaClock className="w-4 h-4" />}
|
||||
<span className="capitalize">{tab}</span>
|
||||
</button>
|
||||
))}
|
||||
|
|
@ -251,7 +251,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200">
|
||||
<div className="px-3 py-3 border-b flex items-center justify-between">
|
||||
<h3 className="text-xl font-semibold text-slate-800 flex items-center">
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
<FaDownload className="w-4 h-4 mr-2" />
|
||||
Template Columns ({editableColumns.length})
|
||||
</h3>
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
disabled={generating}
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 border border-green-200 rounded-md hover:border-green-300 hover:bg-green-50 transition-all duration-200 group disabled:opacity-50 disabled:cursor-not-allowed bg-white text-xs"
|
||||
>
|
||||
<FileSpreadsheet className="w-3.5 h-3.5 text-green-500 group-hover:scale-110 transition-transform" />
|
||||
<FaFileExcel className="w-3.5 h-3.5 text-green-500 group-hover:scale-110 transition-transform" />
|
||||
<span className="font-medium text-slate-700">Excel Template</span>
|
||||
</button>
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
disabled={generating}
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 border border-blue-200 rounded-md hover:border-blue-300 hover:bg-blue-50 transition-all duration-200 group disabled:opacity-50 disabled:cursor-not-allowed bg-white text-xs"
|
||||
>
|
||||
<FileText className="w-3.5 h-3.5 text-blue-500 group-hover:scale-110 transition-transform" />
|
||||
<FaFileAlt className="w-3.5 h-3.5 text-blue-500 group-hover:scale-110 transition-transform" />
|
||||
<span className="font-medium text-slate-700">CSV Template</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -349,7 +349,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
<div className="lg:col-span-1">
|
||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-4 h-full">
|
||||
<h2 className="text-xl font-semibold text-slate-800 mb-4 flex items-center">
|
||||
<Upload className="w-5 h-5 mr-2 text-green-500" />
|
||||
<FaUpload className="w-5 h-5 mr-2 text-green-500" />
|
||||
Upload Data
|
||||
</h2>
|
||||
<FileUploadArea
|
||||
|
|
@ -387,7 +387,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
) : (
|
||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-12">
|
||||
<div className="text-center text-slate-500">
|
||||
<Eye className="w-16 h-16 mx-auto mb-4 text-slate-300" />
|
||||
<FaEye className="w-16 h-16 mx-auto mb-4 text-slate-300" />
|
||||
<div className="text-xl font-medium mb-2">No Data to Preview</div>
|
||||
<div>Upload a file to see the preview here</div>
|
||||
</div>
|
||||
|
|
@ -400,7 +400,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200">
|
||||
<div className="p-3 border-b border-slate-200">
|
||||
<h2 className="text-xl font-semibold text-slate-800 flex items-center">
|
||||
<Clock className="w-5 h-5 mr-2 text-indigo-500" />
|
||||
<FaClock className="w-5 h-5 mr-2 text-indigo-500" />
|
||||
Import History
|
||||
</h2>
|
||||
</div>
|
||||
|
|
@ -458,7 +458,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
}`}
|
||||
title="View execution details"
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
<FaEye className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={async () => {
|
||||
|
|
@ -487,7 +487,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
className="p-2 rounded-lg transition-colors text-slate-400 hover:text-blue-500 hover:bg-blue-50"
|
||||
title="Refresh execution details"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4" />
|
||||
<FaSync className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={async () => {
|
||||
|
|
@ -509,7 +509,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
: 'Delete this import session'
|
||||
}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -521,7 +521,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
<div className="p-3">
|
||||
{loadingExecutes.has(session.id) ? (
|
||||
<div className="flex items-center space-x-2 text-slate-500 py-2">
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
<FaSync className="w-4 h-4 animate-spin" />
|
||||
<span className="text-sm">Loading execution details...</span>
|
||||
</div>
|
||||
) : sessionExecutes[session.id] && sessionExecutes[session.id].length > 0 ? (
|
||||
|
|
@ -561,16 +561,16 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
{/* Sağ: Status */}
|
||||
<div className="flex items-center space-x-2 flex-shrink-0">
|
||||
{execute.status === 'completed' && (
|
||||
<CheckCircle className="w-4 h-4 text-green-500" />
|
||||
<FaCheckCircle className="w-4 h-4 text-green-500" />
|
||||
)}
|
||||
{execute.status === 'processing' && (
|
||||
<RefreshCw className="w-4 h-4 text-blue-500 animate-spin" />
|
||||
<FaSync className="w-4 h-4 text-blue-500 animate-spin" />
|
||||
)}
|
||||
{execute.status === 'validating' && (
|
||||
<Clock className="w-4 h-4 text-yellow-500" />
|
||||
<FaClock className="w-4 h-4 text-yellow-500" />
|
||||
)}
|
||||
{execute.status === 'failed' && (
|
||||
<AlertCircle className="w-4 h-4 text-red-500" />
|
||||
<FaRegBell className="w-4 h-4 text-red-500" />
|
||||
)}
|
||||
<div
|
||||
className={`text-xs font-medium ${
|
||||
|
|
@ -605,7 +605,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
|
||||
{importHistory.length === 0 && (
|
||||
<div className="p-12 text-center text-slate-500">
|
||||
<Clock className="w-12 h-12 mx-auto mb-4 text-slate-300" />
|
||||
<FaClock className="w-12 h-12 mx-auto mb-4 text-slate-300" />
|
||||
<div className="text-lg font-medium mb-2">No import history</div>
|
||||
<div>Your import history will appear here</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { CheckCircle, AlertTriangle, Eye, Play, X } from 'lucide-react'
|
||||
import {
|
||||
FaCheckCircle,
|
||||
FaExclamationTriangle,
|
||||
FaEye,
|
||||
FaPlay,
|
||||
FaTimes
|
||||
} from 'react-icons/fa';
|
||||
import { ListFormImportDto } from '@/proxy/imports/models'
|
||||
import { GridDto } from '@/proxy/form/models'
|
||||
import { ImportService } from '@/services/import.service'
|
||||
|
|
@ -149,7 +155,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-center gap-4">
|
||||
{/* Başlık kısmı - Üstte mobile, solda desktop */}
|
||||
<div className="flex items-center order-1 lg:order-none">
|
||||
<Eye className="w-5 h-5 mr-2 text-blue-500" />
|
||||
<FaEye className="w-5 h-5 mr-2 text-blue-500" />
|
||||
<h3 className="text-xl font-semibold text-slate-800">Import Preview</h3>
|
||||
</div>
|
||||
|
||||
|
|
@ -236,7 +242,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
) : previewData && previewData.headers && previewData.headers.length === 0 ? (
|
||||
<div className="p-6 border-b border-slate-200">
|
||||
<div className="text-center py-8">
|
||||
<AlertTriangle className="w-12 h-12 mx-auto mb-4 text-yellow-500" />
|
||||
<FaExclamationTriangle className="w-12 h-12 mx-auto mb-4 text-yellow-500" />
|
||||
<h4 className="font-semibold text-slate-800 mb-2">No Data Found</h4>
|
||||
<p className="text-slate-600">
|
||||
Unable to parse data from the uploaded file. Please check the file format and content.
|
||||
|
|
@ -259,7 +265,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
{showSuccessMessage && lastExecutionResult && (
|
||||
<div className="mb-4 p-4 bg-green-50 border border-green-200 rounded-lg">
|
||||
<div className="flex items-center space-x-2 text-green-700">
|
||||
<CheckCircle className="w-5 h-5" />
|
||||
<FaCheckCircle className="w-5 h-5" />
|
||||
<span className="font-medium">
|
||||
Import completed successfully! {lastExecutionResult.successCount} of{' '}
|
||||
{lastExecutionResult.selectedCount} rows were imported.
|
||||
|
|
@ -272,21 +278,21 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
<div className="flex items-center space-x-4">
|
||||
{selectedRows.length === 0 && (previewData?.rows?.length || 0) > 0 && (
|
||||
<div className="flex items-center space-x-2 text-orange-600">
|
||||
<AlertTriangle className="w-5 h-5" />
|
||||
<FaExclamationTriangle className="w-5 h-5" />
|
||||
<span className="font-medium">Please select rows to import using checkboxes</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedRows.length > 0 && (
|
||||
<div className="flex items-center space-x-2 text-blue-600">
|
||||
<CheckCircle className="w-5 h-5" />
|
||||
<FaCheckCircle className="w-5 h-5" />
|
||||
<span className="font-medium">{selectedRows.length} rows selected for import</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(previewData?.rows?.length || 0) === 0 && (
|
||||
<div className="flex items-center space-x-2 text-red-600">
|
||||
<AlertTriangle className="w-5 h-5" />
|
||||
<FaExclamationTriangle className="w-5 h-5" />
|
||||
<span className="font-medium">No data available for import</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -294,7 +300,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
|
||||
<div className="flex space-x-3">
|
||||
<button className="px-4 py-2 text-slate-600 hover:text-slate-800 hover:bg-slate-100 rounded-lg transition-colors flex items-center space-x-2">
|
||||
<X className="w-4 h-4" />
|
||||
<FaTimes className="w-4 h-4" />
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
|
||||
|
|
@ -310,7 +316,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<Play className="w-4 h-4" />
|
||||
<FaPlay className="w-4 h-4" />
|
||||
<span>Execute Import</span>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { RefreshCw, Upload, CheckCircle } from 'lucide-react'
|
||||
import { FaSync, FaUpload, FaCheckCircle } from 'react-icons/fa';
|
||||
import { ListFormImportDto } from '@/proxy/imports/models'
|
||||
|
||||
interface ImportProgressProps {
|
||||
|
|
@ -44,14 +44,14 @@ export const ImportProgress: React.FC<ImportProgressProps> = ({ session }) => {
|
|||
const getStatusIcon = () => {
|
||||
switch (session.status) {
|
||||
case 'uploading':
|
||||
return <Upload className="w-6 h-6 text-blue-500" />
|
||||
return <FaUpload className="w-6 h-6 text-blue-500" />
|
||||
case 'validating':
|
||||
case 'processing':
|
||||
return <RefreshCw className="w-6 h-6 text-blue-500 animate-spin" />
|
||||
return <FaSync className="w-6 h-6 text-blue-500 animate-spin" />
|
||||
case 'uploaded':
|
||||
return <CheckCircle className="w-6 h-6 text-green-500" />
|
||||
return <FaCheckCircle className="w-6 h-6 text-green-500" />
|
||||
default:
|
||||
return <RefreshCw className="w-6 h-6 text-blue-500 animate-spin" />
|
||||
return <FaSync className="w-6 h-6 text-blue-500 animate-spin" />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { LayoutDashboard, Database, Zap, Server, Puzzle } from 'lucide-react'
|
||||
import { FaTachometerAlt, FaDatabase, FaBolt, FaServer, FaPuzzlePiece } from 'react-icons/fa';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
|
@ -18,31 +18,31 @@ const DeveloperLayout: React.FC<DeveloperLayoutProps> = ({ children }) => {
|
|||
{
|
||||
id: 'dashboard',
|
||||
label: translate('::App.DeveloperKit.Dashboard'),
|
||||
icon: LayoutDashboard,
|
||||
icon: FaTachometerAlt,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit,
|
||||
},
|
||||
{
|
||||
id: 'entities',
|
||||
label: translate('::App.DeveloperKit.Entity'),
|
||||
icon: Database,
|
||||
icon: FaDatabase,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitEntities,
|
||||
},
|
||||
{
|
||||
id: 'migrations',
|
||||
label: translate('::App.DeveloperKit.Migrations'),
|
||||
icon: Zap,
|
||||
icon: FaBolt,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
},
|
||||
{
|
||||
id: 'endpoints',
|
||||
label: translate('::App.DeveloperKit.Endpoints'),
|
||||
icon: Server,
|
||||
icon: FaServer,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitEndpoints,
|
||||
},
|
||||
{
|
||||
id: 'components',
|
||||
label: translate('::App.DeveloperKit.Components'),
|
||||
icon: Puzzle,
|
||||
icon: FaPuzzlePiece,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitComponents,
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,23 +1,24 @@
|
|||
import View from '@/views/Views'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useLocation, Link } from 'react-router-dom'
|
||||
import {
|
||||
Menu,
|
||||
X,
|
||||
Home,
|
||||
Info,
|
||||
Package,
|
||||
Briefcase,
|
||||
BookOpen,
|
||||
Phone,
|
||||
Facebook,
|
||||
Twitter,
|
||||
Linkedin,
|
||||
Instagram,
|
||||
MapPin,
|
||||
Mail,
|
||||
PlayCircle,
|
||||
} from 'lucide-react'
|
||||
import {
|
||||
FaBars,
|
||||
FaTimes,
|
||||
FaHome,
|
||||
FaInfoCircle,
|
||||
FaVectorSquare,
|
||||
FaBriefcase,
|
||||
FaBook,
|
||||
FaPhone,
|
||||
FaFacebook,
|
||||
FaTwitter,
|
||||
FaLinkedin,
|
||||
FaInstagram,
|
||||
FaMapPin,
|
||||
FaEnvelope,
|
||||
FaPlayCircle,
|
||||
FaBookOpen
|
||||
} from 'react-icons/fa';
|
||||
import Logo from '@/views/public/Logo'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -65,43 +66,43 @@ const PublicLayout = () => {
|
|||
resourceKey: 'Public.nav.home',
|
||||
name: translate('::Public.nav.home'),
|
||||
path: ROUTES_ENUM.public.home,
|
||||
icon: Home,
|
||||
icon: FaHome,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.about',
|
||||
name: translate('::Public.nav.about'),
|
||||
path: ROUTES_ENUM.public.about,
|
||||
icon: Info,
|
||||
icon: FaInfoCircle,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.services',
|
||||
name: translate('::Public.nav.services'),
|
||||
path: ROUTES_ENUM.public.services,
|
||||
icon: Briefcase,
|
||||
icon: FaBriefcase,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.products',
|
||||
name: translate('::Public.nav.products'),
|
||||
path: ROUTES_ENUM.public.products,
|
||||
icon: Package,
|
||||
icon: FaVectorSquare,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.blog',
|
||||
name: translate('::Public.nav.blog'),
|
||||
path: ROUTES_ENUM.public.blog,
|
||||
icon: BookOpen,
|
||||
icon: FaBookOpen,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.demo',
|
||||
name: translate('::Public.nav.demo'),
|
||||
action: () => setIsDemoOpen(true),
|
||||
icon: PlayCircle,
|
||||
icon: FaPlayCircle,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.contact',
|
||||
name: translate('::Public.nav.contact'),
|
||||
path: ROUTES_ENUM.public.contact,
|
||||
icon: Phone,
|
||||
icon: FaPhone,
|
||||
},
|
||||
{
|
||||
resourceKey: 'Public.nav.giris',
|
||||
|
|
@ -162,7 +163,7 @@ const PublicLayout = () => {
|
|||
|
||||
{/* Mobile Menu Button */}
|
||||
<button className="md:hidden text-white" onClick={toggleMenu} aria-label="Toggle menu">
|
||||
{isOpen ? <X size={24} /> : <Menu size={24} />}
|
||||
{isOpen ? <FaTimes size={24} /> : <FaBars size={24} />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -222,7 +223,7 @@ const PublicLayout = () => {
|
|||
rel="noopener noreferrer"
|
||||
className="text-gray-400 hover:text-white transition-colors"
|
||||
>
|
||||
<Facebook size={20} />
|
||||
<FaFacebook size={20} />
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/sozsoft"
|
||||
|
|
@ -230,7 +231,7 @@ const PublicLayout = () => {
|
|||
rel="noopener noreferrer"
|
||||
className="text-gray-400 hover:text-white transition-colors"
|
||||
>
|
||||
<Twitter size={20} />
|
||||
<FaTwitter size={20} />
|
||||
</a>
|
||||
<a
|
||||
href="https://linkedin.com/sozsoft"
|
||||
|
|
@ -238,7 +239,7 @@ const PublicLayout = () => {
|
|||
rel="noopener noreferrer"
|
||||
className="text-gray-400 hover:text-white transition-colors"
|
||||
>
|
||||
<Linkedin size={20} />
|
||||
<FaLinkedin size={20} />
|
||||
</a>
|
||||
<a
|
||||
href="https://instagram.com/sozsoft"
|
||||
|
|
@ -246,7 +247,7 @@ const PublicLayout = () => {
|
|||
rel="noopener noreferrer"
|
||||
className="text-gray-400 hover:text-white transition-colors"
|
||||
>
|
||||
<Instagram size={20} />
|
||||
<FaInstagram size={20} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -372,11 +373,11 @@ const PublicLayout = () => {
|
|||
</h3>
|
||||
<ul className="space-y-3">
|
||||
<li className="flex items-start space-x-3">
|
||||
<MapPin size={20} className="text-gray-400 mt-1 flex-shrink-0" />
|
||||
<FaMapPin size={20} className="text-gray-400 mt-1 flex-shrink-0" />
|
||||
<span className="text-gray-400">{translate('::Public.footer.address')}</span>
|
||||
</li>
|
||||
<li className="flex items-center space-x-3">
|
||||
<Phone size={20} className="text-gray-400 flex-shrink-0" />
|
||||
<FaPhone size={20} className="text-gray-400 flex-shrink-0" />
|
||||
<a
|
||||
href="tel:+905447697638"
|
||||
className="text-gray-400 hover:text-white transition-colors"
|
||||
|
|
@ -385,7 +386,7 @@ const PublicLayout = () => {
|
|||
</a>
|
||||
</li>
|
||||
<li className="flex items-center space-x-3">
|
||||
<Mail size={20} className="text-gray-400 flex-shrink-0" />
|
||||
<FaEnvelope size={20} className="text-gray-400 flex-shrink-0" />
|
||||
<a
|
||||
href="mailto:destek@sozsoft.com"
|
||||
className="text-gray-400 hover:text-white transition-colors"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { Calendar, Clock, Minus, Plus, ShoppingCart } from 'lucide-react'
|
||||
import { FaCalendar, FaClock, FaMinus, FaPlus, FaShoppingCart } from 'react-icons/fa';
|
||||
import { BillingCycle } from '@/proxy/order/models'
|
||||
import { CartState } from '@/utils/cartUtils'
|
||||
import { useScroll } from '@/contexts/ScrollContext'
|
||||
|
|
@ -41,7 +41,7 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
<div className="flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||
<div className="flex items-center space-x-6">
|
||||
<div className="flex items-center space-x-2 rounded-lg">
|
||||
<Calendar className="w-5 h-5 text-gray-600" />
|
||||
<FaCalendar className="w-5 h-5 text-gray-600" />
|
||||
<span className="font-medium text-gray-900">Faturalama Döngüsü:</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
<div className="flex items-center space-x-6">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Clock className="w-5 h-5 text-gray-600" />
|
||||
<FaClock className="w-5 h-5 text-gray-600" />
|
||||
<span className="font-medium text-gray-900">Periyod:</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
disabled={globalPeriod <= 1 || hasCartItems}
|
||||
title={hasCartItems ? 'Sepette ürün varken periyod değiştirilemez' : undefined}
|
||||
>
|
||||
<Minus className="w-4 h-4" />
|
||||
<FaMinus className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<div className="flex items-center space-x-2 bg-gray-50 px-4 py-2 rounded-lg">
|
||||
|
|
@ -119,7 +119,7 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
disabled={hasCartItems}
|
||||
title={hasCartItems ? 'Sepette ürün varken periyod değiştirilemez' : undefined}
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -128,7 +128,7 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
onClick={onCartClick}
|
||||
className="relative flex items-center gap-2 p-2 bg-green-600 text-white hover:bg-green-700 transition-colors rounded-lg shadow-md"
|
||||
>
|
||||
<ShoppingCart className="w-5 h-5" />
|
||||
<FaShoppingCart className="w-5 h-5" />
|
||||
<span className="font-medium text-sm">{translate('::Public.nav.basket')}</span>
|
||||
|
||||
{cartItemsCount > 0 && (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import React from 'react';
|
||||
import { X, Minus, Plus, ShoppingBag, Trash2 } from 'lucide-react';
|
||||
import {
|
||||
FaTimes,
|
||||
FaMinus,
|
||||
FaPlus,
|
||||
FaShoppingBag,
|
||||
FaTrash
|
||||
} from 'react-icons/fa';
|
||||
import { BillingCycle, BasketItem } from '@/proxy/order/models';
|
||||
|
||||
interface CartState {
|
||||
|
|
@ -60,14 +66,14 @@ export const Cart: React.FC<CartProps> = ({
|
|||
className="p-2 text-red-500 hover:bg-red-50 rounded-lg transition-colors"
|
||||
title="Sepeti Temizle"
|
||||
>
|
||||
<Trash2 className="w-5 h-5" />
|
||||
<FaTrash className="w-5 h-5" />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -75,7 +81,7 @@ export const Cart: React.FC<CartProps> = ({
|
|||
<div className="flex-1 overflow-y-auto p-6">
|
||||
{cartState.items.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center h-full text-gray-500">
|
||||
<ShoppingBag className="w-16 h-16 mb-4" />
|
||||
<FaShoppingBag className="w-16 h-16 mb-4" />
|
||||
<p className="text-lg font-medium">Sepetiniz boş</p>
|
||||
<p className="text-sm">Ürün eklemek için katalogdan seçim yapın</p>
|
||||
</div>
|
||||
|
|
@ -91,7 +97,7 @@ export const Cart: React.FC<CartProps> = ({
|
|||
onClick={() => removeItem(item.product.id)}
|
||||
className="text-red-500 hover:text-red-700 ml-2"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<FaTimes className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -115,14 +121,14 @@ export const Cart: React.FC<CartProps> = ({
|
|||
onClick={() => updateQuantity(item.product.id, item.quantity - 1)}
|
||||
className="p-1 rounded border border-gray-300 hover:bg-gray-50"
|
||||
>
|
||||
<Minus className="w-3 h-3" />
|
||||
<FaMinus className="w-3 h-3" />
|
||||
</button>
|
||||
<span className="w-8 text-center text-sm">{item.quantity}</span>
|
||||
<button
|
||||
onClick={() => updateQuantity(item.product.id, item.quantity + 1)}
|
||||
className="p-1 rounded border border-gray-300 hover:bg-gray-50"
|
||||
>
|
||||
<Plus className="w-3 h-3" />
|
||||
<FaPlus className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import React from 'react'
|
||||
import { CheckCircle, Download, ArrowLeft } from 'lucide-react'
|
||||
import {
|
||||
FaCheckCircle,
|
||||
FaArrowLeft
|
||||
} from 'react-icons/fa';
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
|
|
@ -15,7 +18,7 @@ export const OrderSuccess: React.FC<OrderSuccessProps> = ({ orderId, onBackToSho
|
|||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className="bg-white rounded-xl shadow-lg border border-gray-200 p-8">
|
||||
<div className="mb-6">
|
||||
<CheckCircle className="w-16 h-16 text-green-500 mx-auto mb-4" />
|
||||
<FaCheckCircle className="w-16 h-16 text-green-500 mx-auto mb-4" />
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">Siparişiniz Başarıyla Alındı!</h2>
|
||||
<p className="text-gray-600">
|
||||
Sipariş numaranız: <span className="font-semibold text-blue-600">#{orderId}</span>
|
||||
|
|
@ -36,7 +39,7 @@ export const OrderSuccess: React.FC<OrderSuccessProps> = ({ orderId, onBackToSho
|
|||
onClick={() => navigate(ROUTES_ENUM.public.home)}
|
||||
className="flex items-center justify-center px-6 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
<FaArrowLeft className="w-4 h-4 mr-2" />
|
||||
Ana Sayfa'ya Dön
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import {
|
||||
CreditCard,
|
||||
Lock,
|
||||
ArrowLeft,
|
||||
User,
|
||||
Building,
|
||||
Mail,
|
||||
Phone,
|
||||
MapPin,
|
||||
Map,
|
||||
Globe,
|
||||
Banknote,
|
||||
BadgeDollarSign,
|
||||
UserPlus,
|
||||
} from 'lucide-react'
|
||||
import {
|
||||
FaCreditCard,
|
||||
FaLock,
|
||||
FaArrowLeft,
|
||||
FaUser,
|
||||
FaBuilding,
|
||||
FaMailBulk,
|
||||
FaPhone,
|
||||
FaMapMarkerAlt,
|
||||
FaMap,
|
||||
FaGlobe,
|
||||
FaMoneyBillWave,
|
||||
FaDollarSign,
|
||||
FaUserPlus
|
||||
} from 'react-icons/fa';
|
||||
import {
|
||||
BillingCycle,
|
||||
BasketItem,
|
||||
|
|
@ -125,42 +125,42 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({
|
|||
{tenant && (
|
||||
<>
|
||||
<h2 className="text-lg font-semibold mb-4 flex items-center">
|
||||
<User className="w-5 h-5 text-green-600 mr-2" /> Müşteri Bilgileri
|
||||
<FaUser className="w-5 h-5 text-green-600 mr-2" /> Müşteri Bilgileri
|
||||
</h2>
|
||||
<div className="pt-4 border-t border-gray-200">
|
||||
<div className="grid grid-cols-1 gap-y-3 text-sm text-gray-700">
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="w-4 h-4 text-gray-500" />
|
||||
<FaUser className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Kurum Kodu:</span>
|
||||
<span>{tenant.name}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="w-4 h-4 text-gray-500" />
|
||||
<FaUser className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Kurucu:</span>
|
||||
<span>{tenant.founder}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Building className="w-4 h-4 text-gray-500" />
|
||||
<FaBuilding className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Şirket:</span>
|
||||
<span>{tenant.institutionName}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Mail className="w-4 h-4 text-gray-500" />
|
||||
<FaMailBulk className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">E-posta:</span>
|
||||
<span>{tenant.email}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Phone className="w-4 h-4 text-gray-500" />
|
||||
<FaPhone className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Telefon:</span>
|
||||
<span>{tenant.phone}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-2">
|
||||
<MapPin className="w-4 h-4 text-gray-500 mt-0.5" />
|
||||
<FaMapMarkerAlt className="w-4 h-4 text-gray-500 mt-0.5" />
|
||||
<div>
|
||||
<span className="font-medium">Adres:</span>
|
||||
<div>{tenant.address}</div>
|
||||
|
|
@ -168,44 +168,44 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="w-4 h-4 text-gray-500" />
|
||||
<FaGlobe className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Ülke:</span>
|
||||
<span>{tenant.country}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="w-4 h-4 text-gray-500" />
|
||||
<FaGlobe className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Şehir:</span>
|
||||
<span>{tenant.city}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Map className="w-4 h-4 text-gray-500" />
|
||||
<FaMap className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">İlçe:</span>
|
||||
<span>{tenant.district}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<MapPin className="w-4 h-4 text-gray-500" />
|
||||
<FaMapMarkerAlt className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Posta Kodu:</span>
|
||||
<span>{tenant.postalCode}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Banknote className="w-4 h-4 text-gray-500" />
|
||||
<FaMoneyBillWave className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Vergi Dairesi:</span>
|
||||
<span>{tenant.taxOffice}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<BadgeDollarSign className="w-4 h-4 text-gray-500" />
|
||||
<FaDollarSign className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Vergi No:</span>
|
||||
<span>{tenant.vknTckn}</span>
|
||||
</div>
|
||||
|
||||
{tenant.reference && (
|
||||
<div className="flex items-center gap-2">
|
||||
<UserPlus className="w-4 h-4 text-gray-500" />
|
||||
<FaUserPlus className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Referans:</span>
|
||||
<span>{tenant.reference}</span>
|
||||
</div>
|
||||
|
|
@ -221,7 +221,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({
|
|||
{/* 1. Sütun: Ödeme Yöntemi */}
|
||||
<div className="bg-white rounded-xl shadow border p-6">
|
||||
<h2 className="text-lg font-semibold mb-4 flex items-center">
|
||||
<Lock className="w-5 h-5 text-green-600 mr-2" /> Ödeme Yöntemi
|
||||
<FaLock className="w-5 h-5 text-green-600 mr-2" /> Ödeme Yöntemi
|
||||
</h2>
|
||||
<div className="space-y-2">
|
||||
{paymentMethods.map((method) => (
|
||||
|
|
@ -401,14 +401,14 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({
|
|||
onClick={onBack}
|
||||
className="flex items-center px-6 py-3 border border-gray-300 text-gray-700 rounded-lg"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
<FaArrowLeft className="w-4 h-4 mr-2" />
|
||||
Geri
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center justify-center px-6 py-3 bg-green-600 text-white rounded-lg"
|
||||
>
|
||||
<CreditCard className="w-5 h-5 mr-2" />
|
||||
<FaCreditCard className="w-5 h-5 mr-2" />
|
||||
{selectedPaymentMethod === 'bank-transfer' ? 'Siparişi Tamamla' : 'Ödeme Yap'}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Plus, Minus } from 'lucide-react';
|
||||
import { FaPlus, FaMinus } from 'react-icons/fa';
|
||||
import { BillingCycle, Product, ProductDto } from '@/proxy/order/models';
|
||||
import { CartState } from '@/utils/cartUtils';
|
||||
|
||||
|
|
@ -115,14 +115,14 @@ export const ProductCard: React.FC<ProductCardProps> = ({
|
|||
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
||||
className="p-1 rounded-md border border-gray-300 hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<Minus className="w-4 h-4" />
|
||||
<FaMinus className="w-4 h-4" />
|
||||
</button>
|
||||
<span className="w-12 text-center font-medium">{quantity}</span>
|
||||
<button
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
className="p-1 rounded-md border border-gray-300 hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useMemo, useEffect } from 'react'
|
||||
import { Filter, Search } from 'lucide-react'
|
||||
import { FaFilter, FaSearch } from 'react-icons/fa';
|
||||
import { ProductCard } from './ProductCard'
|
||||
import { addItemToCart, CartState } from '@/utils/cartUtils'
|
||||
import { BillingCycle, ProductDto } from '@/proxy/order/models'
|
||||
|
|
@ -86,7 +86,7 @@ export const ProductCatalog: React.FC<ProductCatalogProps> = ({
|
|||
<aside className="lg:w-64 flex-shrink-0">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 sticky top-40">
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<Filter className="w-5 h-5 text-gray-600" />
|
||||
<FaFilter className="w-5 h-5 text-gray-600" />
|
||||
<h3 className="font-semibold text-gray-900">Kategoriler</h3>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
|
|
@ -117,11 +117,11 @@ export const ProductCatalog: React.FC<ProductCatalogProps> = ({
|
|||
{/* Search input moved here */}
|
||||
<div className="mt-6">
|
||||
<div className="flex items-center space-x-2 mb-3">
|
||||
<Search className="w-5 h-5 text-gray-600" />
|
||||
<FaSearch className="w-5 h-5 text-gray-600" />
|
||||
<h3 className="font-semibold text-gray-900">Arama</h3>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
|
||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Ürün ara..."
|
||||
|
|
@ -154,7 +154,7 @@ export const ProductCatalog: React.FC<ProductCatalogProps> = ({
|
|||
{filteredProducts.length === 0 && (
|
||||
<div className="text-center py-12">
|
||||
<div className="text-gray-400 mb-2">
|
||||
<Filter className="w-12 h-12 mx-auto" />
|
||||
<FaFilter className="w-12 h-12 mx-auto" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">Ürün bulunamadı</h3>
|
||||
<p className="text-gray-600">Arama kriterlerinizi değiştirmeyi deneyin.</p>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import { getTenantByNameDetail } from '@/services/tenant.service'
|
||||
import { CustomTenantDto } from '@/proxy/config/models'
|
||||
import {
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
BadgeDollarSign,
|
||||
Banknote,
|
||||
Building,
|
||||
Globe,
|
||||
Mail,
|
||||
Map,
|
||||
MapPin,
|
||||
Phone,
|
||||
Search,
|
||||
User,
|
||||
UserPlus,
|
||||
} from 'lucide-react'
|
||||
FaArrowLeft,
|
||||
FaArrowRight,
|
||||
FaDollarSign,
|
||||
FaMoneyBillWave,
|
||||
FaBuilding,
|
||||
FaGlobe,
|
||||
FaEnvelope,
|
||||
FaMap,
|
||||
FaMapPin,
|
||||
FaPhone,
|
||||
FaSearch,
|
||||
FaUser,
|
||||
FaUserPlus,
|
||||
} from 'react-icons/fa'
|
||||
import React, { useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div className="w-full lg:w-1/3 bg-white rounded-xl shadow-lg border border-gray-200 p-6">
|
||||
<div className="mb-6">
|
||||
<h2 className="text-lg font-semibold mb-4 flex items-center">
|
||||
<User className="w-5 h-5 text-green-600 mr-2" /> Müşteri Bilgileri
|
||||
<FaUser className="w-5 h-5 text-green-600 mr-2" /> Müşteri Bilgileri
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<label className="block text-sm font-medium text-gray-700 mb-2">Kurum Kodu *</label>
|
||||
<div className="relative flex flex-col sm:flex-row sm:items-stretch">
|
||||
<div className="relative w-full">
|
||||
<Building className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -136,7 +136,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
onClick={getTenantInfo}
|
||||
className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-600 text-white rounded-lg sm:rounded-r-lg sm:rounded-l-none hover:bg-blue-700 transition-colors min-w-[148px]"
|
||||
>
|
||||
<Search className="w-4 h-4" />
|
||||
<FaSearch className="w-4 h-4" />
|
||||
Kurumu Bul
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -144,31 +144,31 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
{formData.institutionName && (
|
||||
<div className="grid grid-cols-1 gap-y-3 text-sm text-gray-700 p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="w-4 h-4 text-gray-500" />
|
||||
<FaUser className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Kurucu:</span>
|
||||
<span>{formData.founder}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Building className="w-4 h-4 text-gray-500" />
|
||||
<FaBuilding className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Şirket:</span>
|
||||
<span>{formData.institutionName}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Mail className="w-4 h-4 text-gray-500" />
|
||||
<FaEnvelope className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">E-posta:</span>
|
||||
<span>{formData.email}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Phone className="w-4 h-4 text-gray-500" />
|
||||
<FaPhone className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Mobile:</span>
|
||||
<span>{formData.mobile}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-2">
|
||||
<MapPin className="w-4 h-4 text-gray-500 mt-0.5" />
|
||||
<FaMapPin className="w-4 h-4 text-gray-500 mt-0.5" />
|
||||
<div>
|
||||
<span className="font-medium">Adres:</span>
|
||||
<div>{formData.address}</div>
|
||||
|
|
@ -176,44 +176,44 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="w-4 h-4 text-gray-500" />
|
||||
<FaGlobe className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Ülke:</span>
|
||||
<span>{formData.country}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="w-4 h-4 text-gray-500" />
|
||||
<FaGlobe className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Şehir:</span>
|
||||
<span>{formData.city}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Map className="w-4 h-4 text-gray-500" />
|
||||
<FaMap className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">İlçe:</span>
|
||||
<span>{formData.district}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<MapPin className="w-4 h-4 text-gray-500" />
|
||||
<FaMapPin className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Posta Kodu:</span>
|
||||
<span>{formData.postalCode}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Banknote className="w-4 h-4 text-gray-500" />
|
||||
<FaMoneyBillWave className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Vergi Dairesi:</span>
|
||||
<span>{formData.taxOffice}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<BadgeDollarSign className="w-4 h-4 text-gray-500" />
|
||||
<FaDollarSign className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Vergi No:</span>
|
||||
<span>{formData.vknTckn}</span>
|
||||
</div>
|
||||
|
||||
{formData.reference && (
|
||||
<div className="flex items-center gap-2">
|
||||
<UserPlus className="w-4 h-4 text-gray-500" />
|
||||
<FaUserPlus className="w-4 h-4 text-gray-500" />
|
||||
<span className="font-medium">Referans:</span>
|
||||
<span>{formData.reference}</span>
|
||||
</div>
|
||||
|
|
@ -229,7 +229,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
Şirket Adı *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Building className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -244,7 +244,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Kurucu *</label>
|
||||
<div className="relative">
|
||||
<User className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaUser className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -261,7 +261,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Telefon *</label>
|
||||
<div className="relative">
|
||||
<Phone className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaPhone className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="tel"
|
||||
required
|
||||
|
|
@ -275,7 +275,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">E-posta *</label>
|
||||
<div className="relative">
|
||||
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaEnvelope className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
|
|
@ -291,7 +291,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Adres *</label>
|
||||
<div className="relative">
|
||||
<MapPin className="absolute left-3 top-3 text-gray-400 w-5 h-5" />
|
||||
<FaMapPin className="absolute left-3 top-3 text-gray-400 w-5 h-5" />
|
||||
<textarea
|
||||
required
|
||||
placeholder="Enter your address"
|
||||
|
|
@ -307,7 +307,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Ülke</label>
|
||||
<div className="relative">
|
||||
<Globe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Türkiye"
|
||||
|
|
@ -320,7 +320,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Şehir *</label>
|
||||
<div className="relative">
|
||||
<Globe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -337,7 +337,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">İlçe *</label>
|
||||
<div className="relative">
|
||||
<Map className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -351,7 +351,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Posta Kodu *</label>
|
||||
<div className="relative">
|
||||
<MapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -368,7 +368,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Vergi Dairesi *</label>
|
||||
<div className="relative">
|
||||
<Banknote className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -382,7 +382,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Vergi No *</label>
|
||||
<div className="relative">
|
||||
<BadgeDollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaDollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
|
|
@ -398,7 +398,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">Referans</label>
|
||||
<div className="relative">
|
||||
<UserPlus className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<FaUserPlus className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Referans kişi veya kodu"
|
||||
|
|
@ -417,14 +417,14 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
onClick={() => navigate('/products')}
|
||||
className="flex items-center px-6 py-3 border border-gray-300 text-gray-700 rounded-lg"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
<FaArrowLeft className="w-4 h-4 mr-2" />
|
||||
Geri
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center justify-center px-6 py-3 bg-green-600 text-white rounded-lg"
|
||||
>
|
||||
<ArrowRight className="w-5 h-5 mr-2" />
|
||||
<FaArrowRight className="w-5 h-5 mr-2" />
|
||||
Devam Et
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@ import React, { useState, useMemo, useEffect } from 'react'
|
|||
import { TemplateEditor } from '../reports/TemplateEditor'
|
||||
import { ReportGenerator } from '../reports/ReportGenerator'
|
||||
import { TemplateCard } from './TemplateCard'
|
||||
import { Button } from '../ui/Button'
|
||||
import { Input } from '../ui/Input'
|
||||
import { Plus, Search, Filter, FileText, BarChart3 } from 'lucide-react'
|
||||
import { Button, Input} from '../ui'
|
||||
import {
|
||||
FaPlus,
|
||||
FaSearch,
|
||||
FaFilter,
|
||||
FaFileAlt,
|
||||
FaChartBar
|
||||
} from 'react-icons/fa';
|
||||
import { ReportCategoryDto, ReportTemplateDto } from '@/proxy/reports/models'
|
||||
import { useReports } from '@/utils/hooks/useReports'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -187,7 +192,7 @@ export const Dashboard: React.FC = () => {
|
|||
<div className="flex items-center space-x-4">
|
||||
{/* Search Input */}
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||
<Input
|
||||
placeholder="Şablon ara..."
|
||||
value={searchQuery}
|
||||
|
|
@ -202,7 +207,7 @@ export const Dashboard: React.FC = () => {
|
|||
onClick={handleCreateTemplate}
|
||||
className="bg-blue-600 hover:bg-blue-700 font-medium px-6 py-2.5 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 flex items-center space-x-2"
|
||||
>
|
||||
<Plus className="h-5 w-5" />
|
||||
<FaPlus className="h-5 w-5" />
|
||||
<span>Yeni Şablon</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -219,7 +224,7 @@ export const Dashboard: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-gray-900">{filteredTemplates.length}</p>
|
||||
</div>
|
||||
<div className="bg-blue-100 p-3 rounded-full">
|
||||
<FileText className="h-6 w-6 text-blue-600" />
|
||||
<FaFileAlt className="h-6 w-6 text-blue-600" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -231,7 +236,7 @@ export const Dashboard: React.FC = () => {
|
|||
<p className="text-2xl font-bold text-gray-900">{categories.length}</p>
|
||||
</div>
|
||||
<div className="bg-emerald-100 p-3 rounded-full">
|
||||
<Filter className="h-6 w-6 text-emerald-600" />
|
||||
<FaFilter className="h-6 w-6 text-emerald-600" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -247,7 +252,7 @@ export const Dashboard: React.FC = () => {
|
|||
</p>
|
||||
</div>
|
||||
<div className="bg-purple-100 p-3 rounded-full">
|
||||
<BarChart3 className="h-6 w-6 text-purple-600" />
|
||||
<FaChartBar className="h-6 w-6 text-purple-600" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -256,7 +261,7 @@ export const Dashboard: React.FC = () => {
|
|||
{/* Templates Grid */}
|
||||
{filteredTemplates.length === 0 ? (
|
||||
<div className="bg-white rounded-xl shadow-md p-12 border border-gray-200 text-center">
|
||||
<FileText className="h-16 w-16 text-gray-400 mx-auto mb-4" />
|
||||
<FaFileAlt className="h-16 w-16 text-gray-400 mx-auto mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
||||
{templates.length === 0 ? 'Henüz şablon oluşturulmamış' : 'Şablon bulunamadı'}
|
||||
</h3>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import React, { useState } from 'react'
|
||||
import { Button } from '../ui/Button'
|
||||
import { Input } from '../ui/Input'
|
||||
import { FileText } from 'lucide-react'
|
||||
import { Button, Input, Dialog } from '../ui'
|
||||
import { FaFileAlt } from 'react-icons/fa';
|
||||
import { ReportTemplateDto } from '@/proxy/reports/models'
|
||||
import { Dialog } from '../ui'
|
||||
|
||||
interface ReportGeneratorProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -109,7 +107,7 @@ export const ReportGenerator: React.FC<ReportGeneratorProps> = ({
|
|||
</div>
|
||||
) : (
|
||||
<div className="py-8 text-gray-500">
|
||||
<FileText className="h-12 w-12 text-gray-400 mx-auto mb-4" />
|
||||
<FaFileAlt className="h-12 w-12 text-gray-400 mx-auto mb-4" />
|
||||
<p>Bu şablon için parametre tanımlanmamış.</p>
|
||||
<p className="text-sm">Direkt rapor oluşturabilirsiniz.</p>
|
||||
</div>
|
||||
|
|
@ -123,7 +121,7 @@ export const ReportGenerator: React.FC<ReportGeneratorProps> = ({
|
|||
className="bg-blue-600 hover:bg-blue-700 font-medium px-2 sm:px-3 py-1.5 rounded text-xs flex items-center gap-1"
|
||||
|
||||
>
|
||||
<FileText className="h-4 w-4 mr-2" />
|
||||
<FaFileAlt className="h-4 w-4 mr-2" />
|
||||
{isGenerating ? 'Oluşturuluyor...' : 'Rapor Oluştur'}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { Button } from '../ui/Button'
|
||||
import { ArrowLeft, Calendar, FileText, Download, ZoomIn, ZoomOut } from 'lucide-react'
|
||||
import {
|
||||
FaArrowLeft,
|
||||
FaCalendarAlt,
|
||||
FaFileAlt,
|
||||
FaDownload,
|
||||
FaSearchPlus,
|
||||
FaSearchMinus,
|
||||
} from 'react-icons/fa'
|
||||
import html2canvas from 'html2canvas'
|
||||
import jsPDF from 'jspdf'
|
||||
import { ReportGeneratedDto, ReportTemplateDto } from '@/proxy/reports/models'
|
||||
|
|
@ -131,7 +138,7 @@ export const ReportViewer: React.FC = () => {
|
|||
<div className="text-center">
|
||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">{error || 'Rapor bulunamadı'}</h1>
|
||||
<Button onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
<FaArrowLeft className="h-4 w-4 mr-2" />
|
||||
Ana Sayfaya Dön
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -145,7 +152,7 @@ export const ReportViewer: React.FC = () => {
|
|||
<div className="text-center">
|
||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">Rapor bulunamadı</h1>
|
||||
<Button onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
<FaArrowLeft className="h-4 w-4 mr-2" />
|
||||
Ana Sayfaya Dön
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -163,7 +170,7 @@ export const ReportViewer: React.FC = () => {
|
|||
Aradığınız rapor mevcut değil veya silinmiş olabilir.
|
||||
</p>
|
||||
<Button onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
<FaArrowLeft className="h-4 w-4 mr-2" />
|
||||
Ana Sayfaya Dön
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -242,7 +249,7 @@ export const ReportViewer: React.FC = () => {
|
|||
<h1 className="text-lg font-semibold text-gray-900">{report.templateName}</h1>
|
||||
<div className="flex items-center space-x-4 text-sm text-gray-500">
|
||||
<span className="flex items-center">
|
||||
<Calendar className="h-4 w-4 mr-1" />
|
||||
<FaCalendarAlt className="h-4 w-4 mr-1" />
|
||||
{new Date(report.generatedAt).toLocaleDateString('tr-TR', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
|
|
@ -253,7 +260,7 @@ export const ReportViewer: React.FC = () => {
|
|||
</span>
|
||||
{template && (
|
||||
<span className="flex items-center">
|
||||
<FileText className="h-4 w-4 mr-1" />
|
||||
<FaFileAlt className="h-4 w-4 mr-1" />
|
||||
{template.categoryName}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -263,23 +270,25 @@ export const ReportViewer: React.FC = () => {
|
|||
|
||||
<div className="flex items-center space-x-2 flex-shrink-0">
|
||||
<Button variant="solid" onClick={handleZoomOut} disabled={zoomLevel <= 50} size="sm">
|
||||
<ZoomOut className="h-4 w-4" />
|
||||
<FaSearchMinus className="h-4 w-4" />
|
||||
</Button>
|
||||
<span className="text-sm text-gray-600 px-2 min-w-[4rem] text-center">
|
||||
{zoomLevel}%
|
||||
</span>
|
||||
<Button variant="solid" onClick={handleZoomIn} disabled={zoomLevel >= 200} size="sm">
|
||||
<ZoomIn className="h-4 w-4" />
|
||||
<FaSearchPlus className="h-4 w-4" />
|
||||
</Button>
|
||||
<div className="w-px h-6 bg-gray-300 mx-2"></div>
|
||||
<Button
|
||||
onClick={handleDownloadPdf}
|
||||
className="bg-white-600 hover:bg-white-700 font-medium px-2 sm:px-3 py-1.5 rounded text-xs flex items-center gap-1"
|
||||
>
|
||||
<Download className="h-4 w-4 mr-2" />
|
||||
<FaDownload className="h-4 w-4 mr-2" />
|
||||
PDF İndir
|
||||
</Button>
|
||||
<Button variant="solid" onClick={handlePrint}>Yazdır</Button>
|
||||
<Button variant="solid" onClick={handlePrint}>
|
||||
Yazdır
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react'
|
||||
import { Button } from '../ui/Button'
|
||||
import { FileText, Edit, Trash2, Play } from 'lucide-react'
|
||||
import { FaFileAlt, FaEdit, FaTrash, FaPlay } from 'react-icons/fa';
|
||||
import { ReportTemplateDto } from '@/proxy/reports/models'
|
||||
|
||||
interface TemplateCardProps {
|
||||
|
|
@ -27,7 +27,7 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-1 flex-shrink-0 bg-gray-50 px-2 py-1 rounded-lg">
|
||||
<FileText className="h-4 w-4 text-blue-500" />
|
||||
<FaFileAlt className="h-4 w-4 text-blue-500" />
|
||||
<span className="text-xs text-gray-500 whitespace-nowrap">{template.parameters.length}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -69,7 +69,7 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
|
|||
onClick={() => onGenerate(template)}
|
||||
className="bg-gray-600 hover:bg-gray-700 font-medium px-3 py-1.5 rounded text-xs flex items-center gap-1 flex-1 justify-center min-w-0"
|
||||
>
|
||||
<Play className="h-3 w-3" />
|
||||
<FaPlay className="h-3 w-3" />
|
||||
<span className="truncate">Göster</span>
|
||||
</Button>
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
|
|||
onClick={() => onEdit(template)}
|
||||
className="font-medium px-3 py-1.5 rounded text-xs flex items-center gap-1 flex-1 justify-center min-w-0"
|
||||
>
|
||||
<Edit className="h-3 w-3" />
|
||||
<FaEdit className="h-3 w-3" />
|
||||
<span className="truncate">Düzenle</span>
|
||||
</Button>
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
|
|||
onClick={() => onDelete(template.id)}
|
||||
className="bg-red-600 hover:bg-red-700 font-medium px-3 py-1.5 rounded text-xs flex items-center justify-center flex-1 min-w-0"
|
||||
>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
<FaTrash className="h-3 w-3" />
|
||||
<span className="truncate">Sil</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { Save, X, FileText, Code, Settings } from 'lucide-react'
|
||||
import { FaSave, FaTimes, FaFileAlt, FaCode, FaCog } from 'react-icons/fa'
|
||||
import { ReportHtmlEditor } from './ReportHtmlEditor'
|
||||
import { ReportParameterDto, ReportTemplateDto, ReportCategoryDto } from '@/proxy/reports/models'
|
||||
import { Button, Input, Dialog } from '../ui'
|
||||
|
|
@ -132,15 +132,15 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
setFormData((prev) => ({
|
||||
...prev,
|
||||
parameters: prev.parameters.map((param) =>
|
||||
param.id === paramId ? { ...param, ...updates } : param
|
||||
param.id === paramId ? { ...param, ...updates } : param,
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{ id: 'info', label: translate('::Şablon Bilgileri'), icon: FileText },
|
||||
{ id: 'parameters', label: translate('::Parametreler'), icon: Settings },
|
||||
{ id: 'content', label: translate('::HTML İçerik'), icon: Code },
|
||||
{ id: 'info', label: translate('::Şablon Bilgileri'), icon: FaFileAlt },
|
||||
{ id: 'parameters', label: translate('::Parametreler'), icon: FaCog },
|
||||
{ id: 'content', label: translate('::HTML İçerik'), icon: FaCode },
|
||||
]
|
||||
|
||||
return (
|
||||
|
|
@ -250,7 +250,7 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
onClick={() => removeTag(tag)}
|
||||
className="ml-2 text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
<FaTimes className="h-3 w-3" />
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
|
|
@ -303,7 +303,7 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
<div className="max-w-full mx-auto">
|
||||
{formData.parameters.length === 0 ? (
|
||||
<div className="text-center py-12">
|
||||
<Settings className="h-16 w-16 text-gray-400 mx-auto mb-4" />
|
||||
<FaCog className="h-16 w-16 text-gray-400 mx-auto mb-4" />
|
||||
<p className="text-gray-500 text-lg mb-2">Henüz parametre algılanmadı</p>
|
||||
<p className="text-gray-400 text-sm">
|
||||
HTML içeriğinde @@PARAMETRE formatında parametreler kullandığınızda burada
|
||||
|
|
@ -326,7 +326,9 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
</div>
|
||||
<select
|
||||
value={param.type}
|
||||
onChange={(e) => updateParameter(param.id, { type: e.target.value as any })}
|
||||
onChange={(e) =>
|
||||
updateParameter(param.id, { type: e.target.value as any })
|
||||
}
|
||||
className="text-xs bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded-full flex-shrink-0 ml-1 border-none outline-none cursor-pointer"
|
||||
>
|
||||
<option value="text">text</option>
|
||||
|
|
@ -336,12 +338,14 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
<option value="checkbox">checkbox</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="mb-2">
|
||||
<input
|
||||
type="text"
|
||||
value={param.description || ''}
|
||||
onChange={(e) => updateParameter(param.id, { description: e.target.value })}
|
||||
onChange={(e) =>
|
||||
updateParameter(param.id, { description: e.target.value })
|
||||
}
|
||||
placeholder="Parametre açıklaması"
|
||||
className="w-full text-xs text-gray-600 bg-transparent border-none outline-none resize-none"
|
||||
/>
|
||||
|
|
@ -351,7 +355,9 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={param.defaultValue || ''}
|
||||
onChange={(e) => updateParameter(param.id, { defaultValue: e.target.value })}
|
||||
onChange={(e) =>
|
||||
updateParameter(param.id, { defaultValue: e.target.value })
|
||||
}
|
||||
placeholder="Varsayılan değer"
|
||||
className="w-full text-xs bg-gray-50 px-1.5 py-0.5 rounded border border-gray-200 outline-none"
|
||||
/>
|
||||
|
|
@ -362,7 +368,9 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
<input
|
||||
type="checkbox"
|
||||
checked={param.required}
|
||||
onChange={(e) => updateParameter(param.id, { required: e.target.checked })}
|
||||
onChange={(e) =>
|
||||
updateParameter(param.id, { required: e.target.checked })
|
||||
}
|
||||
className="w-3 h-3 text-red-600 rounded border-gray-300 focus:ring-red-500"
|
||||
/>
|
||||
<span className="text-xs text-gray-600">Zorunlu</span>
|
||||
|
|
@ -388,7 +396,7 @@ export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|||
onClick={handleSave}
|
||||
className="bg-blue-600 hover:bg-blue-700 font-medium px-2 py-2 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 flex items-center space-x-2"
|
||||
>
|
||||
<Save className="h-5 w-5" />
|
||||
<FaSave className="h-5 w-5" />
|
||||
{isSaving ? 'Kaydediliyor...' : template ? 'Güncelle' : 'Kaydet'}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import navigationIcon from '@/configs/navigation-icon.config'
|
||||
import type { ElementType, ComponentPropsWithRef } from 'react'
|
||||
import React from 'react'
|
||||
import { FaQuestionCircle } from 'react-icons/fa'
|
||||
|
||||
type HorizontalMenuIconProps = {
|
||||
icon: string
|
||||
|
|
@ -16,11 +18,14 @@ export const Icon = <T extends ElementType>({
|
|||
}
|
||||
|
||||
const HorizontalMenuIcon = ({ icon }: HorizontalMenuIconProps) => {
|
||||
if (typeof icon !== 'string' && !icon) {
|
||||
if (typeof icon !== 'string' || !icon) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return <span className="text-xl ltr:mr-2 rtl:ml-2">{navigationIcon[icon]}</span>
|
||||
// React.createElement ile dinamik ikon bileşenini render et
|
||||
const IconComponent = navigationIcon[icon] || FaQuestionCircle // fallback ikon
|
||||
|
||||
return <span className="text-xl ltr:mr-2 rtl:ml-2">{React.createElement(IconComponent)}</span>
|
||||
}
|
||||
|
||||
export default HorizontalMenuIcon
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import navigationIcon from '@/configs/navigation-icon.config'
|
|||
import MenuItem from '@/components/ui/MenuItem'
|
||||
import HorizontalMenuNavLink from './HorizontalMenuNavLink'
|
||||
import type { NavMode } from '@/@types/theme'
|
||||
import React from 'react'
|
||||
import { FaQuestionCircle } from 'react-icons/fa'
|
||||
|
||||
export type HorizontalMenuItemProps = {
|
||||
nav: {
|
||||
|
|
@ -19,7 +21,9 @@ export type HorizontalMenuItemProps = {
|
|||
const HorizontalMenuItem = ({ nav, isLink, manuVariant }: HorizontalMenuItemProps) => {
|
||||
const { title, icon, path, isExternalLink } = nav
|
||||
|
||||
const renderIcon = icon && <span className="text-2xl">{navigationIcon[icon]}</span>
|
||||
// Dinamik ikon render etmek için createElement kullanıyoruz
|
||||
const renderIcon =
|
||||
icon && React.createElement(navigationIcon[icon] || FaQuestionCircle, { className: 'text-2xl' })
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ import {
|
|||
import { useStoreState } from '@/store'
|
||||
import useMenuActive from '@/utils/hooks/useMenuActive'
|
||||
import isEmpty from 'lodash/isEmpty'
|
||||
import React from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import { FaQuestionCircle } from 'react-icons/fa'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
|
||||
export type SelectedMenuItem = {
|
||||
|
|
@ -116,7 +118,9 @@ const StackedSideNavMini = (props: StackedSideNavMiniProps) => {
|
|||
})
|
||||
}
|
||||
>
|
||||
<div className="text-2xl">{navigationIcon[nav.icon]}</div>
|
||||
<div className="text-2xl">
|
||||
{React.createElement(navigationIcon[nav.icon] || FaQuestionCircle)}{' '}
|
||||
</div>
|
||||
</Menu.MenuItem>
|
||||
) : (
|
||||
<Link
|
||||
|
|
@ -129,7 +133,9 @@ const StackedSideNavMini = (props: StackedSideNavMiniProps) => {
|
|||
}
|
||||
>
|
||||
<Menu.MenuItem icon={nav.icon} eventKey={nav.key} className="mb-2">
|
||||
<div className="text-2xl">{navigationIcon[nav.icon]}</div>
|
||||
<div className="text-2xl">
|
||||
{React.createElement(navigationIcon[nav.icon] || FaQuestionCircle)}
|
||||
</div>
|
||||
</Menu.MenuItem>
|
||||
</Link>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import navigationIcon from '@/configs/navigation-icon.config'
|
||||
import type { ElementType, ComponentPropsWithRef } from 'react'
|
||||
import React from 'react'
|
||||
|
||||
type VerticalMenuIconProps = {
|
||||
icon: string
|
||||
|
|
@ -16,11 +17,23 @@ export const Icon = <T extends ElementType>({
|
|||
}
|
||||
|
||||
const VerticalMenuIcon = ({ icon }: VerticalMenuIconProps) => {
|
||||
if (typeof icon !== 'string' && !icon) {
|
||||
// Eğer icon boş veya string değilse, boş bir öğe döndür
|
||||
if (typeof icon !== 'string' || !icon) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return <span className="text-2xl ltr:mr-2 rtl:ml-2">{navigationIcon[icon]}</span>
|
||||
// navigationIcon'dan ikonu al ve React.createElement ile render et
|
||||
const IconComponent = navigationIcon[icon]
|
||||
|
||||
if (!IconComponent) {
|
||||
return <></> // İkon bulunamazsa, boş döndür
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="text-2xl ltr:mr-2 rtl:ml-2">
|
||||
{React.createElement(IconComponent)} {/* İkonu dinamik olarak render et */}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default VerticalMenuIcon
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import { createElement } from 'react'
|
||||
import * as fc from 'react-icons/fc'
|
||||
import * as fa from 'react-icons/fa'
|
||||
|
||||
export type NavigationIcons = Record<string, JSX.Element>
|
||||
export type NavigationIcons = Record<string, React.ComponentType<any>>;
|
||||
|
||||
const navigationIcon: NavigationIcons = {}
|
||||
const navigationIcon: NavigationIcons = {};
|
||||
|
||||
for (const icon of Object.entries(fc)) {
|
||||
navigationIcon[icon[0]] = createElement(icon[1])
|
||||
// fc (Font Awesome) ikonlarıyla dinamik olarak navigationIcon nesnesini doldur
|
||||
for (const [key, Icon] of Object.entries(fc)) {
|
||||
navigationIcon[key] = Icon; // Icon bileşenini doğrudan kullanıyoruz
|
||||
}
|
||||
|
||||
for (const icon of Object.entries(fa)) {
|
||||
navigationIcon[icon[0]] = createElement(icon[1])
|
||||
// fa (Font Awesome) ikonlarıyla navigationIcon nesnesini doldur
|
||||
for (const [key, Icon] of Object.entries(fa)) {
|
||||
navigationIcon[key] = Icon; // Icon bileşenini doğrudan kullanıyoruz
|
||||
}
|
||||
|
||||
export default navigationIcon
|
||||
export default navigationIcon;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useRef, useEffect, SyntheticEvent } from 'react'
|
||||
import { Bot } from 'lucide-react'
|
||||
import { FaRobot } from 'react-icons/fa';
|
||||
import { useStoreActions, useStoreState } from '@/store'
|
||||
import { Avatar, Dropdown } from '@/components/ui'
|
||||
import LoadAiPostsFromLocalStorage from './LoadAiPostsFromLocalStorage'
|
||||
|
|
@ -276,7 +276,7 @@ const Assistant = () => {
|
|||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
{messages.length === 0 && (
|
||||
<div className="text-center text-gray-500 mt-8">
|
||||
<Bot className="w-12 h-12 mx-auto mb-4 text-gray-400" />
|
||||
<FaRobot className="w-12 h-12 mx-auto mb-4 text-gray-400" />
|
||||
<p className="mt-2">{translate('::AI.Welcome')}</p>
|
||||
<p className="text-lg font-medium">{translate('::AI.Name')}</p>
|
||||
</div>
|
||||
|
|
@ -293,7 +293,7 @@ const Assistant = () => {
|
|||
{msg.role === 'user' ? (
|
||||
<Avatar size={32} shape="circle" src={avatar} alt="avatar" />
|
||||
) : (
|
||||
<Bot className="w-5 h-5 text-white" />
|
||||
<FaRobot className="w-5 h-5 text-white" />
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { GridColumnData } from '../list/GridColumnData'
|
|||
import { useToolbar } from '../list/useToolbar'
|
||||
import { PermissionResults, RowMode } from './types'
|
||||
import { GridDto } from '@/proxy/form/models'
|
||||
import React from 'react'
|
||||
|
||||
const FormButtons = (props: {
|
||||
mode: RowMode
|
||||
|
|
@ -108,8 +109,13 @@ const FormButtons = (props: {
|
|||
key={'toolbarButton-' + i}
|
||||
variant="default"
|
||||
size="sm"
|
||||
{...(item.options?.icon ? { icon: navigationIcon[item.options.icon] } : {})}
|
||||
// title={translate(item.options.hint)} // TODO: translate('::' + item.options.hint) mu olmalı?
|
||||
{...(item.options?.icon
|
||||
? {
|
||||
icon: React.createElement(navigationIcon[item.options.icon], {
|
||||
className: 'text-gray-400',
|
||||
}),
|
||||
}
|
||||
: {})}
|
||||
onClick={item.options.onClick}
|
||||
>
|
||||
{item.options.text}
|
||||
|
|
@ -130,7 +136,13 @@ const FormButtons = (props: {
|
|||
key={'commandColumnButton-' + i}
|
||||
variant="default"
|
||||
size="sm"
|
||||
{...(item.icon ? { icon: navigationIcon[item.icon] } : {})}
|
||||
{...(item.icon
|
||||
? {
|
||||
icon: React.createElement(navigationIcon[item.icon], {
|
||||
className: 'text-gray-400',
|
||||
}),
|
||||
}
|
||||
: {})}
|
||||
title={item.hint}
|
||||
onClick={(e: any) => {
|
||||
if (item.onClick) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react'
|
||||
import { Folder, MessageSquare, FileText, Plus, BarChart3 } from 'lucide-react'
|
||||
import { FaFolder, FaCommentAlt, FaFileAlt, FaChartBar } from 'react-icons/fa'
|
||||
import { CategoryManagement } from './CategoryManagement'
|
||||
import { TopicManagement } from './TopicManagement'
|
||||
import { PostManagement } from './PostManagement'
|
||||
|
|
@ -81,22 +81,22 @@ export function AdminView({
|
|||
{
|
||||
id: 'stats' as AdminSection,
|
||||
label: translate('::App.Forum.Dashboard.Dashboard'),
|
||||
icon: BarChart3,
|
||||
icon: FaChartBar,
|
||||
},
|
||||
{
|
||||
id: 'categories' as AdminSection,
|
||||
label: translate('::App.Forum.Dashboard.Categories'),
|
||||
icon: Folder,
|
||||
icon: FaFolder,
|
||||
},
|
||||
{
|
||||
id: 'topics' as AdminSection,
|
||||
label: translate('::App.Forum.Dashboard.Topics'),
|
||||
icon: MessageSquare,
|
||||
icon: FaCommentAlt,
|
||||
},
|
||||
{
|
||||
id: 'posts' as AdminSection,
|
||||
label: translate('::App.Forum.Dashboard.Posts'),
|
||||
icon: FileText,
|
||||
icon: FaFileAlt,
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
import React, { useState } from 'react'
|
||||
import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react'
|
||||
import {
|
||||
FaPlus,
|
||||
FaEdit,
|
||||
FaTrash,
|
||||
FaLock,
|
||||
FaUnlock,
|
||||
FaEye,
|
||||
FaEyeSlash,
|
||||
FaSpinner,
|
||||
} from 'react-icons/fa'
|
||||
import { ForumCategory } from '@/proxy/forum/forum'
|
||||
import { useStoreState } from '@/store/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -161,7 +170,7 @@ export function CategoryManagement({
|
|||
disabled={loading}
|
||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
<span>{translate('::App.Forum.CategoryManagement.AddCategory')}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -320,7 +329,7 @@ export function CategoryManagement({
|
|||
|
||||
{loading ? (
|
||||
<div className="p-8 text-center">
|
||||
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||
<FaSpinner className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||
<p className="text-gray-500">
|
||||
{translate('::App.Forum.CategoryManagement.Loadingcategories')}
|
||||
</p>
|
||||
|
|
@ -368,9 +377,9 @@ export function CategoryManagement({
|
|||
title={category.isActive ? 'Hide Category' : 'Show Category'}
|
||||
>
|
||||
{category.isActive ? (
|
||||
<Eye className="w-4 h-4" />
|
||||
<FaEye className="w-4 h-4" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
<FaEyeSlash className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
|
|
@ -384,9 +393,9 @@ export function CategoryManagement({
|
|||
title={category.isLocked ? 'Unlock Category' : 'Lock Category'}
|
||||
>
|
||||
{category.isLocked ? (
|
||||
<Lock className="w-4 h-4" />
|
||||
<FaLock className="w-4 h-4" />
|
||||
) : (
|
||||
<Unlock className="w-4 h-4" />
|
||||
<FaUnlock className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
|
|
@ -395,7 +404,7 @@ export function CategoryManagement({
|
|||
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
||||
title={translate('::App.Forum.CategoryManagement.EditCategory')}
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
<FaEdit className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
|
|
@ -403,7 +412,7 @@ export function CategoryManagement({
|
|||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||
title={translate('::App.Forum.CategoryManagement.DeleteCategory')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrash className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -437,8 +446,7 @@ export function CategoryManagement({
|
|||
setCategoryToDelete(null)
|
||||
}
|
||||
}}
|
||||
>
|
||||
</ConfirmDialog>
|
||||
></ConfirmDialog>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Folder, MessageSquare, FileText, TrendingUp } from 'lucide-react'
|
||||
import { FaFolder, FaCommentDots, FaFileAlt, FaChartLine } from 'react-icons/fa';
|
||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import dayjs from 'dayjs'
|
||||
|
|
@ -31,28 +31,28 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) {
|
|||
title: translate('::App.Forum.Dashboard.TotalCategories'),
|
||||
value: totalCategories,
|
||||
subtitle: `${activeCategories} active`,
|
||||
icon: Folder,
|
||||
icon: FaFolder,
|
||||
color: 'bg-blue-500',
|
||||
},
|
||||
{
|
||||
title: translate('::App.Forum.Dashboard.TotalTopics'),
|
||||
value: totalTopics,
|
||||
subtitle: `${solvedTopics} solved`,
|
||||
icon: MessageSquare,
|
||||
icon: FaCommentDots,
|
||||
color: 'bg-emerald-500',
|
||||
},
|
||||
{
|
||||
title: translate('::App.Forum.Dashboard.TotalPosts'),
|
||||
value: totalPosts,
|
||||
subtitle: `${acceptedAnswers} accepted answers`,
|
||||
icon: FileText,
|
||||
icon: FaFileAlt,
|
||||
color: 'bg-orange-500',
|
||||
},
|
||||
{
|
||||
title: translate('::App.Forum.Dashboard.EngagementRate'),
|
||||
value: totalTopics > 0 ? Math.round((totalPosts / totalTopics) * 100) / 100 : 0,
|
||||
subtitle: 'posts per topic',
|
||||
icon: TrendingUp,
|
||||
icon: FaChartLine,
|
||||
color: 'bg-purple-500',
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react'
|
||||
import { Plus, Edit2, Trash2, CheckCircle, Circle, Heart, Loader2 } from 'lucide-react'
|
||||
import { FaPlus, FaEdit, FaTrashAlt, FaCheckCircle, FaCircle, FaHeart, FaSpinner } from 'react-icons/fa';
|
||||
import { ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
import { HtmlEditor, ImageUpload, Item, MediaResizing, Toolbar } from 'devextreme-react/html-editor'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
|
@ -169,7 +169,7 @@ export function PostManagement({
|
|||
disabled={loading}
|
||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
<span>{translate('::App.Forum.PostManagement.AddPost')}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -351,7 +351,7 @@ export function PostManagement({
|
|||
|
||||
{loading ? (
|
||||
<div className="p-8 text-center">
|
||||
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||
<FaSpinner className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||
<p className="text-gray-500">{translate('::App.Forum.PostManagement.Loadingtopics')}</p>
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -368,7 +368,7 @@ export function PostManagement({
|
|||
<h4 className="text-sm font-semibold text-gray-900">{post.authorName}</h4>
|
||||
{post.isAcceptedAnswer && (
|
||||
<div className="flex items-center space-x-1 bg-emerald-100 text-emerald-700 px-2 py-1 rounded-full text-xs">
|
||||
<CheckCircle className="w-3 h-3" />
|
||||
<FaCheckCircle className="w-3 h-3" />
|
||||
<span>Accepted Answer</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -389,7 +389,7 @@ export function PostManagement({
|
|||
<div className="flex items-center space-x-4">
|
||||
<span>{formatDate(post.creationTime)}</span>
|
||||
<div className="flex items-center space-x-1">
|
||||
<Heart className="w-4 h-4" />
|
||||
<FaHeart className="w-4 h-4" />
|
||||
<span>{post.likeCount} likes</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -411,9 +411,9 @@ export function PostManagement({
|
|||
}
|
||||
>
|
||||
{post.isAcceptedAnswer ? (
|
||||
<CheckCircle className="w-4 h-4" />
|
||||
<FaCheckCircle className="w-4 h-4" />
|
||||
) : (
|
||||
<Circle className="w-4 h-4" />
|
||||
<FaCircle className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ export function PostManagement({
|
|||
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
||||
title={translate('::App.Forum.PostManagement.EditPost')}
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
<FaEdit className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
|
|
@ -430,7 +430,7 @@ export function PostManagement({
|
|||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||
title={translate('::App.Forum.PostManagement.DeletePost')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import React, { useState } from 'react'
|
||||
import {
|
||||
Plus,
|
||||
Edit2,
|
||||
Trash2,
|
||||
Lock,
|
||||
Unlock,
|
||||
Pin,
|
||||
PinOff,
|
||||
CheckCircle,
|
||||
Circle,
|
||||
Eye,
|
||||
Loader2,
|
||||
} from 'lucide-react'
|
||||
FaPlus,
|
||||
FaEdit,
|
||||
FaTrashAlt,
|
||||
FaLock,
|
||||
FaUnlock,
|
||||
FaThumbtack,
|
||||
FaCheckCircle,
|
||||
FaCircle,
|
||||
FaEye,
|
||||
FaSpinner,
|
||||
FaTree,
|
||||
} from 'react-icons/fa'
|
||||
import { ForumCategory, ForumTopic } from '@/proxy/forum/forum'
|
||||
import { useStoreState } from '@/store/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -219,7 +219,7 @@ export function TopicManagement({
|
|||
disabled={loading}
|
||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
<span>{translate('::App.Forum.TopicManagement.AddTopic')}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -362,7 +362,7 @@ export function TopicManagement({
|
|||
|
||||
{loading ? (
|
||||
<div className="p-8 text-center">
|
||||
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||
<FaSpinner className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||
<p className="text-gray-500">
|
||||
{translate('::App.Forum.TopicManagement.Loadingtopics')}
|
||||
</p>
|
||||
|
|
@ -378,9 +378,9 @@ export function TopicManagement({
|
|||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center space-x-2 mb-2">
|
||||
{topic.isPinned && <Pin className="w-4 h-4 text-orange-500" />}
|
||||
{topic.isLocked && <Lock className="w-4 h-4 text-gray-400" />}
|
||||
{topic.isSolved && <CheckCircle className="w-4 h-4 text-emerald-500" />}
|
||||
{topic.isPinned && <FaThumbtack className="w-4 h-4 text-orange-500" />}
|
||||
{topic.isLocked && <FaLock className="w-4 h-4 text-gray-400" />}
|
||||
{topic.isSolved && <FaCheckCircle className="w-4 h-4 text-emerald-500" />}
|
||||
<h4 className="text-lg font-semibold text-gray-900 line-clamp-1">
|
||||
{topic.title}
|
||||
</h4>
|
||||
|
|
@ -396,7 +396,7 @@ export function TopicManagement({
|
|||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center space-x-1">
|
||||
<Eye className="w-4 h-4" />
|
||||
<FaEye className="w-4 h-4" />
|
||||
<span>{topic.viewCount}</span>
|
||||
</div>
|
||||
<span>{topic.replyCount} replies</span>
|
||||
|
|
@ -416,9 +416,9 @@ export function TopicManagement({
|
|||
title={topic.isPinned ? 'Unpin Topic' : 'Pin Topic'}
|
||||
>
|
||||
{topic.isPinned ? (
|
||||
<PinOff className="w-4 h-4" />
|
||||
<FaThumbtack className="w-4 h-4" />
|
||||
) : (
|
||||
<Pin className="w-4 h-4" />
|
||||
<FaTree className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
|
|
@ -432,9 +432,9 @@ export function TopicManagement({
|
|||
title={topic.isLocked ? 'Unlock Topic' : 'Lock Topic'}
|
||||
>
|
||||
{topic.isLocked ? (
|
||||
<Lock className="w-4 h-4" />
|
||||
<FaLock className="w-4 h-4" />
|
||||
) : (
|
||||
<Unlock className="w-4 h-4" />
|
||||
<FaUnlock className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
|
|
@ -448,9 +448,9 @@ export function TopicManagement({
|
|||
title={topic.isSolved ? 'Mark as Unsolved' : 'Mark as Solved'}
|
||||
>
|
||||
{topic.isSolved ? (
|
||||
<CheckCircle className="w-4 h-4" />
|
||||
<FaCheckCircle className="w-4 h-4" />
|
||||
) : (
|
||||
<Circle className="w-4 h-4" />
|
||||
<FaCircle className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
|
|
@ -459,7 +459,7 @@ export function TopicManagement({
|
|||
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
||||
title={translate('::App.Forum.TopicManagement.EditTopic')}
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
<FaEdit className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
|
|
@ -467,7 +467,7 @@ export function TopicManagement({
|
|||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||
title={translate('::App.Forum.TopicManagement.DeleteTopic')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<FaTrashAlt className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -501,8 +501,7 @@ export function TopicManagement({
|
|||
setTopicToDelete(null)
|
||||
}
|
||||
}}
|
||||
>
|
||||
</ConfirmDialog>
|
||||
></ConfirmDialog>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { X } from 'lucide-react'
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
import { Formik, Form, Field, FieldProps } from 'formik'
|
||||
import * as Yup from 'yup'
|
||||
import { HtmlEditor, ImageUpload, Item, MediaResizing, Toolbar } from 'devextreme-react/html-editor'
|
||||
|
|
@ -60,7 +60,7 @@ export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostM
|
|||
: translate('::App.Forum.PostManagement.NewPost')}
|
||||
</h3>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition-colors">
|
||||
<X className="w-5 h-5" />
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { X } from 'lucide-react'
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
import { useStoreState } from '@/store/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Field, FieldProps, Form, Formik } from 'formik'
|
||||
|
|
@ -44,7 +44,7 @@ export function CreateTopicModal({ onClose, onSubmit }: CreateTopicModalProps) {
|
|||
{translate('::App.Forum.TopicManagement.NewTopic')}
|
||||
</h3>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition-colors">
|
||||
<X className="w-5 h-5" />
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import { MessageSquare, Lock, TrendingUp } from 'lucide-react'
|
||||
import { FaComment, FaLock, FaArrowUp } from 'react-icons/fa';
|
||||
import { ForumCategory } from '@/proxy/forum/forum'
|
||||
|
||||
interface CategoryCardProps {
|
||||
|
|
@ -35,16 +34,16 @@ export function ForumCategoryCard({ category, onClick }: CategoryCardProps) {
|
|||
<h3 className="text-lg font-semibold text-gray-900 group-hover:text-blue-600 transition-colors">
|
||||
{category.name}
|
||||
</h3>
|
||||
{category.isLocked && <Lock className="w-4 h-4 text-gray-400" />}
|
||||
{category.isLocked && <FaLock className="w-4 h-4 text-gray-400" />}
|
||||
</div>
|
||||
<p className="text-gray-600 text-sm mb-3 line-clamp-2">{category.description}</p>
|
||||
<div className="flex items-center space-x-4 text-sm text-gray-500">
|
||||
<div className="flex items-center space-x-1">
|
||||
<MessageSquare className="w-4 h-4" />
|
||||
<FaComment className="w-4 h-4" />
|
||||
<span>{category.topicCount} topics</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
<FaArrowUp className="w-4 h-4" />
|
||||
<span>{category.postCount} posts</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { Heart, User, CheckCircle, Reply } from 'lucide-react'
|
||||
import { FaHeart, FaCheckCircle, FaReply } from 'react-icons/fa';
|
||||
import { ForumPost } from '@/proxy/forum/forum'
|
||||
import { AVATAR_URL } from '@/constants/app.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -56,7 +56,7 @@ export function ForumPostCard({
|
|||
<h4 className="text-sm font-semibold text-gray-900">{post.authorName}</h4>
|
||||
{post.isAcceptedAnswer && (
|
||||
<div className="flex items-center space-x-1 bg-emerald-100 text-emerald-700 px-2 py-1 rounded-full text-xs">
|
||||
<CheckCircle className="w-3 h-3" />
|
||||
<FaCheckCircle className="w-3 h-3" />
|
||||
<span>{translate('::App.Forum.PostManagement.AcceptedAnswer')}</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -80,7 +80,7 @@ export function ForumPostCard({
|
|||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
<Heart className={`w-4 h-4 ${isLiked ? 'fill-current' : ''}`} />
|
||||
<FaHeart className={`w-4 h-4 ${isLiked ? 'fill-current' : ''}`} />
|
||||
<span>{post.likeCount}</span>
|
||||
</button>
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ export function ForumPostCard({
|
|||
onClick={() => onReply(post.id)}
|
||||
className="flex items-center space-x-1 px-3 py-1 rounded-full text-sm bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
<Reply className="w-4 h-4" />
|
||||
<FaReply className="w-4 h-4" />
|
||||
<span>{translate('::App.Forum.PostManagement.PostReply')}</span>
|
||||
</button>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import { MessageSquare, Heart, Eye, Pin, Lock, CheckCircle } from 'lucide-react'
|
||||
import { FaComment, FaHeart, FaEye, FaThumbtack, FaLock, FaCheckCircle } from 'react-icons/fa';
|
||||
import { ForumTopic } from '@/proxy/forum/forum'
|
||||
import { AVATAR_URL } from '@/constants/app.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -34,9 +33,9 @@ export function ForumTopicCard({ topic, onClick }: TopicCardProps) {
|
|||
{/* Sol taraf: Başlık, içerik, istatistik */}
|
||||
<div className="flex-1 min-w-0 pr-4">
|
||||
<div className="flex items-center space-x-2 mb-2">
|
||||
{topic.isPinned && <Pin className="w-4 h-4 text-orange-500" />}
|
||||
{topic.isLocked && <Lock className="w-4 h-4 text-gray-400" />}
|
||||
{topic.isSolved && <CheckCircle className="w-4 h-4 text-emerald-500" />}
|
||||
{topic.isPinned && <FaThumbtack className="w-4 h-4 text-orange-500" />}
|
||||
{topic.isLocked && <FaLock className="w-4 h-4 text-gray-400" />}
|
||||
{topic.isSolved && <FaCheckCircle className="w-4 h-4 text-emerald-500" />}
|
||||
<h3 className="text-lg font-semibold text-gray-900 group-hover:text-blue-600 transition-colors line-clamp-1">
|
||||
{topic.title}
|
||||
</h3>
|
||||
|
|
@ -46,15 +45,15 @@ export function ForumTopicCard({ topic, onClick }: TopicCardProps) {
|
|||
|
||||
<div className="flex items-center space-x-4 text-sm text-gray-500">
|
||||
<div className="flex items-center space-x-1" title="Views">
|
||||
<Eye className="w-4 h-4" />
|
||||
<FaEye className="w-4 h-4" />
|
||||
<span>{topic.viewCount}</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1" title="Replies">
|
||||
<MessageSquare className="w-4 h-4" />
|
||||
<FaComment className="w-4 h-4" />
|
||||
<span>{topic.replyCount}</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1" title="Likes">
|
||||
<Heart className="w-4 h-4" />
|
||||
<FaHeart className="w-4 h-4" />
|
||||
<span>{topic.likeCount}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react'
|
||||
import { ArrowLeft, Plus, Loader2, Search } from 'lucide-react'
|
||||
import { FaArrowLeft, FaPlus, FaSpinner, FaSearch } from 'react-icons/fa';
|
||||
import { CreateTopicModal } from './CreateTopicModal'
|
||||
import { CreatePostModal } from './CreatePostModal'
|
||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
|
|
@ -292,7 +292,7 @@ export function ForumView({
|
|||
return (
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-blue-600" />
|
||||
<FaSpinner className="w-8 h-8 animate-spin text-blue-600" />
|
||||
<span className="ml-2 text-gray-600">Loading forum data...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -311,7 +311,7 @@ export function ForumView({
|
|||
onClick={handleBack}
|
||||
className="flex items-center space-x-1 text-blue-600 hover:text-blue-700 transition-colors"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
<FaArrowLeft className="w-4 h-4" />
|
||||
<span>Back</span>
|
||||
</button>
|
||||
)}
|
||||
|
|
@ -357,7 +357,7 @@ export function ForumView({
|
|||
onClick={() => setShowCreateTopic(true)}
|
||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
<span>{translate('::App.Forum.TopicManagement.NewTopic')}</span>
|
||||
</button>
|
||||
)}
|
||||
|
|
@ -366,7 +366,7 @@ export function ForumView({
|
|||
onClick={() => setShowCreatePost(true)}
|
||||
className="flex items-center space-x-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
<FaPlus className="w-4 h-4" />
|
||||
<span>{translate('::App.Forum.PostManagement.NewPost')}</span>
|
||||
</button>
|
||||
)}
|
||||
|
|
@ -376,7 +376,7 @@ export function ForumView({
|
|||
onClick={() => setIsSearchModalOpen(true)}
|
||||
className="hidden md:flex items-center space-x-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<Search className="w-4 h-4 text-gray-400" />
|
||||
<FaSearch className="w-4 h-4 text-gray-400" />
|
||||
<span className="text-gray-500">{translate('::App.Forum.TopicManagement.Searchtopics')}</span>
|
||||
<kbd className="hidden sm:inline-block px-2 py-1 text-xs font-semibold text-gray-500 bg-gray-100 border border-gray-200 rounded">
|
||||
⌘K
|
||||
|
|
@ -387,7 +387,7 @@ export function ForumView({
|
|||
onClick={() => setIsSearchModalOpen(true)}
|
||||
className="md:hidden p-2 text-gray-400 hover:text-gray-600 transition-colors"
|
||||
>
|
||||
<Search className="w-5 h-5" />
|
||||
<FaSearch className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { X, Search, Folder, MessageSquare, FileText, User } from 'lucide-react'
|
||||
import { FaTimes, FaSearch, FaFolder, FaRegComment, FaFileAlt } from 'react-icons/fa'
|
||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
import { useForumSearch } from '@/utils/hooks/useForumSearch'
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ export function SearchModal({
|
|||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center pt-20 p-4 z-50">
|
||||
<div className="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-[70vh] overflow-hidden">
|
||||
<div className="flex items-center p-4 border-b border-gray-200">
|
||||
<Search className="w-5 h-5 text-gray-400 mr-3" />
|
||||
<FaSearch className="w-5 h-5 text-gray-400 mr-3" />
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
|
|
@ -121,14 +121,14 @@ export function SearchModal({
|
|||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600 transition-colors ml-3"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="overflow-y-auto max-h-96">
|
||||
{!searchQuery.trim() ? (
|
||||
<div className="p-8 text-center text-gray-500">
|
||||
<Search className="w-12 h-12 mx-auto mb-4 text-gray-300" />
|
||||
<FaSearch className="w-12 h-12 mx-auto mb-4 text-gray-300" />
|
||||
<p>Start typing to search categories, topics, and posts...</p>
|
||||
</div>
|
||||
) : !hasResults ? (
|
||||
|
|
@ -157,7 +157,7 @@ export function SearchModal({
|
|||
<div className="flex items-center space-x-3 flex-1">
|
||||
<div className="flex-shrink-0">
|
||||
<div className="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center">
|
||||
<Folder className="w-4 h-4 text-blue-600" />
|
||||
<FaFolder className="w-4 h-4 text-blue-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
|
|
@ -197,7 +197,7 @@ export function SearchModal({
|
|||
<div className="flex items-center space-x-3 flex-1">
|
||||
<div className="flex-shrink-0">
|
||||
<div className="w-8 h-8 bg-emerald-100 rounded-lg flex items-center justify-center">
|
||||
<MessageSquare className="w-4 h-4 text-emerald-600" />
|
||||
<FaRegComment className="w-4 h-4 text-emerald-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
|
|
@ -241,7 +241,7 @@ export function SearchModal({
|
|||
<div className="flex items-center space-x-3 flex-1">
|
||||
<div className="flex-shrink-0">
|
||||
<div className="w-8 h-8 bg-orange-100 rounded-lg flex items-center justify-center">
|
||||
<FileText className="w-4 h-4 text-orange-600" />
|
||||
<FaFileAlt className="w-4 h-4 text-orange-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@ import {
|
|||
import { Field, FieldProps, Form, Formik } from 'formik'
|
||||
import { SelectBoxOption } from '@/shared/types'
|
||||
import * as Yup from 'yup'
|
||||
import { ExternalLink, FileText, Plus, Trash2 } from 'lucide-react'
|
||||
import {
|
||||
FaExternalLinkAlt,
|
||||
FaPlus,
|
||||
FaTrashAlt
|
||||
} from 'react-icons/fa';
|
||||
import { MenuDto } from '@/proxy/menus/models'
|
||||
|
||||
interface MenuItemComponentProps {
|
||||
|
|
@ -43,7 +47,7 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
|
|||
permissions,
|
||||
}) => {
|
||||
const { translate } = useLocalization()
|
||||
|
||||
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||
id: item.id || '',
|
||||
data: {
|
||||
|
|
@ -124,17 +128,21 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
|
|||
{isDesignMode && (
|
||||
<div className="flex gap-2 items-center mr-2">
|
||||
<button onClick={() => setIsModalOpen(true)} title="New Item">
|
||||
<Plus size={16} className="text-green-600 hover:text-green-800" />
|
||||
<FaPlus size={16} className="text-green-600 hover:text-green-800" />
|
||||
</button>
|
||||
<button onClick={handleDelete} title="Delete Item">
|
||||
<Trash2 size={16} className="text-red-600 hover:text-red-800" />
|
||||
<FaTrashAlt size={16} className="text-red-600 hover:text-red-800" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-3 flex-1 min-w-0">
|
||||
<div className="flex-shrink-0 text-gray-600 text-xl">
|
||||
{navigationIcon[item.icon || ''] ?? <FaQuestionCircle className="text-gray-400" />}
|
||||
{navigationIcon[item.icon || ''] ? (
|
||||
React.createElement(navigationIcon[item.icon || ''], { className: 'text-gray-400' })
|
||||
) : (
|
||||
<FaQuestionCircle className="text-gray-400" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<span
|
||||
|
|
@ -146,7 +154,7 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
|
|||
{translate('::' + item.displayName)}
|
||||
</span>
|
||||
|
||||
{item.url && <ExternalLink size={12} className="flex-shrink-0 text-gray-400" />}
|
||||
{item.url && <FaExternalLinkAlt size={12} className="flex-shrink-0 text-gray-400" />}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 flex-shrink-0">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,12 @@ import React, { useState } from 'react'
|
|||
import { SortableMenuTree } from './SortableMenuTree'
|
||||
import { MenuItem } from '@/@types/menu'
|
||||
import { useMenuData } from '@/utils/hooks/useMenuData'
|
||||
import { AlertCircle, Loader2, Menu, Save } from 'lucide-react'
|
||||
import {
|
||||
FaRegBell,
|
||||
FaSpinner,
|
||||
FaBars,
|
||||
FaRegSave
|
||||
} from 'react-icons/fa';
|
||||
import { Container } from '@/components/shared'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -53,7 +58,7 @@ export const MenuManager = () => {
|
|||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||
<div className="flex items-center gap-3 text-gray-600">
|
||||
<Loader2 size={24} className="animate-spin" />
|
||||
<FaSpinner className="animate-spin" />
|
||||
<span className="text-lg">Loading menu configuration...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -65,7 +70,7 @@ export const MenuManager = () => {
|
|||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||
<div className="bg-white p-8 rounded-lg shadow-md max-w-md w-full mx-4">
|
||||
<div className="flex items-center gap-3 text-red-600 mb-4">
|
||||
<AlertCircle size={24} />
|
||||
<FaRegBell size={24} />
|
||||
<h2 className="text-lg font-semibold">Error Loading Menu</h2>
|
||||
</div>
|
||||
<p className="text-gray-600 mb-6">{error}</p>
|
||||
|
|
@ -92,7 +97,7 @@ export const MenuManager = () => {
|
|||
<div className="flex items-center justify-between mb-6 flex-wrap gap-4">
|
||||
{/* Sol kısım: Başlık */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Menu size={20} className="text-gray-600" />
|
||||
<FaBars size={20} className="text-gray-600" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">Menu Manager</h2>
|
||||
<span className="text-sm text-gray-500">({menuItems.length} root items)</span>
|
||||
</div>
|
||||
|
|
@ -133,12 +138,12 @@ export const MenuManager = () => {
|
|||
>
|
||||
{isSaving ? (
|
||||
<>
|
||||
<Loader2 size={16} className="animate-spin" />
|
||||
<FaSpinner size={16} className="animate-spin" />
|
||||
Saving...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Save size={16} />
|
||||
<FaRegSave size={16} />
|
||||
Save Changes
|
||||
</>
|
||||
)}
|
||||
|
|
@ -156,7 +161,7 @@ export const MenuManager = () => {
|
|||
/>
|
||||
) : (
|
||||
<div className="text-center py-12 text-gray-500">
|
||||
<Menu size={24} className="mx-auto mb-4 text-gray-300" />
|
||||
<FaBars size={24} className="mx-auto mb-4 text-gray-300" />
|
||||
<p className="text-lg">No menu items found</p>
|
||||
<p className="text-sm">Try refreshing the page or contact your administrator</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
import React from 'react'
|
||||
import { Users, Award, Clock, Globe2 } from 'lucide-react'
|
||||
import {
|
||||
FaUsers,
|
||||
FaAward,
|
||||
FaClock,
|
||||
FaGlobe
|
||||
} from 'react-icons/fa';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useCountUp } from '@/utils/hooks/useCountUp'
|
||||
import { Helmet } from 'react-helmet'
|
||||
|
|
@ -45,26 +50,26 @@ const About: React.FC = () => {
|
|||
<div className="container mx-auto px-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
||||
<div className="text-center" ref={clientsCount.elementRef}>
|
||||
<Users className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<FaUsers className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">
|
||||
{clientsCount.displayValue}
|
||||
</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.clients')}</div>
|
||||
</div>
|
||||
<div className="text-center" ref={experienceCount.elementRef}>
|
||||
<Award className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<FaAward className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">
|
||||
{experienceCount.displayValue}
|
||||
</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.experience')}</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<Clock className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<FaClock className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">7/24</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.support')}</div>
|
||||
</div>
|
||||
<div className="text-center" ref={countriesCount.elementRef}>
|
||||
<Globe2 className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<FaGlobe className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">
|
||||
{countriesCount.displayValue}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Calendar, Clock, User, Tag, Search } from 'lucide-react'
|
||||
import {
|
||||
FaCalendarAlt,
|
||||
FaUser,
|
||||
FaTag,
|
||||
FaSearch
|
||||
} from 'react-icons/fa';
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/tr'
|
||||
import { BlogCategory, BlogPost } from '@/proxy/blog/blog'
|
||||
|
|
@ -110,7 +115,7 @@ const Blog = () => {
|
|||
placeholder="Blog yazılarında ara..."
|
||||
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
<Search className="absolute left-3 top-2.5 h-5 w-5 text-gray-400" />
|
||||
<FaSearch className="absolute left-3 top-2.5 h-5 w-5 text-gray-400" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
@ -181,7 +186,7 @@ const Blog = () => {
|
|||
key={index}
|
||||
className="inline-flex items-center text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded"
|
||||
>
|
||||
<Tag className="w-3 h-3 mr-1" />
|
||||
<FaTag className="w-3 h-3 mr-1" />
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
|
|
@ -190,11 +195,11 @@ const Blog = () => {
|
|||
|
||||
<div className="flex items-center text-sm text-gray-500 space-x-4">
|
||||
<div className="flex items-center">
|
||||
<User size={16} className="mr-1" />
|
||||
<FaUser size={16} className="mr-1" />
|
||||
{post.author.name}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Calendar size={16} className="mr-1" />
|
||||
<FaCalendarAlt size={16} className="mr-1" />
|
||||
{dayjs(post.publishedAt || post.creationTime).format('DD MMM YYYY')}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react'
|
||||
import {
|
||||
Mail,
|
||||
Phone,
|
||||
MapPin,
|
||||
FileText,
|
||||
Building,
|
||||
CalendarDays,
|
||||
CalendarCheck,
|
||||
MessageCircle,
|
||||
} from 'lucide-react'
|
||||
FaMailBulk,
|
||||
FaPhone,
|
||||
FaMapPin,
|
||||
FaFileAlt,
|
||||
FaBuilding,
|
||||
FaCalendarAlt,
|
||||
FaCalendarCheck,
|
||||
FaRegComment
|
||||
} from 'react-icons/fa';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Helmet } from 'react-helmet'
|
||||
|
||||
|
|
@ -53,19 +53,19 @@ const Contact: React.FC = () => {
|
|||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-start space-x-4">
|
||||
<MapPin className="w-6 h-6 text-blue-600 flex-shrink-0 mt-1" />
|
||||
<FaMapPin className="w-6 h-6 text-blue-600 flex-shrink-0 mt-1" />
|
||||
<div>
|
||||
<p className="text-gray-600">{translate('::Public.contact.address.full')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start space-x-4">
|
||||
<Phone className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<FaPhone className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<div>
|
||||
<p className="text-gray-600">+90 (544) 769 7 638</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start space-x-4">
|
||||
<Mail className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<FaMailBulk className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<div>
|
||||
<p className="text-gray-600">
|
||||
<a
|
||||
|
|
@ -78,13 +78,13 @@ const Contact: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex items-start space-x-4">
|
||||
<Building className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<FaBuilding className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<div>
|
||||
<p className="text-gray-600">Kozyatağı</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start space-x-4">
|
||||
<FileText className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<FaFileAlt className="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||
<div>
|
||||
<p className="text-gray-600">32374982750</p>
|
||||
</div>
|
||||
|
|
@ -124,19 +124,19 @@ const Contact: React.FC = () => {
|
|||
<div className="flex items-start space-x-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<CalendarDays className="w-5 h-5 text-blue-500" />
|
||||
<FaCalendarAlt className="w-5 h-5 text-blue-500" />
|
||||
<p className="text-gray-600">
|
||||
{translate('::Public.contact.workHours.weekday')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<CalendarCheck className="w-5 h-5 text-blue-500" />
|
||||
<FaCalendarCheck className="w-5 h-5 text-blue-500" />
|
||||
<p className="text-gray-600">
|
||||
{translate('::Public.contact.workHours.weekend')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<MessageCircle className="w-5 h-5 text-green-500" />
|
||||
<FaRegComment className="w-5 h-5 text-green-500" />
|
||||
<p className="text-gray-600">
|
||||
{translate('::Public.contact.workHours.whatsapp')}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
Building2,
|
||||
User,
|
||||
Mail,
|
||||
Phone,
|
||||
MapPin,
|
||||
Users,
|
||||
MessageSquare,
|
||||
Send,
|
||||
CheckCircle,
|
||||
} from "lucide-react";
|
||||
FaBuilding,
|
||||
FaUser,
|
||||
FaEnvelope,
|
||||
FaPhone,
|
||||
FaMapPin,
|
||||
FaUsers,
|
||||
FaRegComment,
|
||||
FaPaperPlane,
|
||||
FaCheckCircle
|
||||
} from 'react-icons/fa';
|
||||
import { useLocalization } from "@/utils/hooks/useLocalization";
|
||||
|
||||
interface DemoModalProps {
|
||||
|
|
@ -131,7 +131,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
</button>
|
||||
|
||||
<div className="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="w-8 h-8 text-white" />
|
||||
<FaCheckCircle className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-800 mb-4">
|
||||
Teşekkürler!
|
||||
|
|
@ -189,7 +189,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.company')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Building2 className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaBuilding className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
|
|
@ -212,7 +212,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.fullName')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<User className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaUser className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
name="fullName"
|
||||
|
|
@ -235,7 +235,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.email')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaEnvelope className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
|
|
@ -256,7 +256,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.phone')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Phone className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaPhone className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
|
|
@ -279,7 +279,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.address')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<MapPin className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaMapPin className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
name="address"
|
||||
|
|
@ -302,7 +302,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.branchCount')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Building2 className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaBuilding className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="number"
|
||||
name="numberOfBranches"
|
||||
|
|
@ -324,7 +324,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.userCount')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Users className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<FaUsers className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
<input
|
||||
type="number"
|
||||
name="numberOfUsers"
|
||||
|
|
@ -348,7 +348,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
{translate('::Public.common.message')} *
|
||||
</label>
|
||||
<div className="relative">
|
||||
<MessageSquare className="absolute left-3 top-3 w-5 h-5 text-gray-400" />
|
||||
<FaRegComment className="absolute left-3 top-3 w-5 h-5 text-gray-400" />
|
||||
<textarea
|
||||
name="message"
|
||||
value={formData.message}
|
||||
|
|
@ -369,7 +369,7 @@ const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
|
|||
type="submit"
|
||||
className="w-full bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white font-semibold py-4 px-6 rounded-xl transition-all duration-300 transform hover:scale-[1.02] hover:shadow-lg flex items-center justify-center gap-2"
|
||||
>
|
||||
<Send className="w-5 h-5" />
|
||||
<FaPaperPlane className="w-5 h-5" />
|
||||
{translate('::Public.demo.send')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import {
|
||||
ArrowRight,
|
||||
Calendar,
|
||||
Users,
|
||||
Shield,
|
||||
Monitor,
|
||||
Smartphone,
|
||||
Server,
|
||||
Database,
|
||||
BarChart,
|
||||
BookOpen,
|
||||
CreditCard,
|
||||
MessageSquare,
|
||||
Phone,
|
||||
} from 'lucide-react'
|
||||
FaArrowRight,
|
||||
FaCalendarAlt,
|
||||
FaUsers,
|
||||
FaShieldAlt,
|
||||
FaDesktop,
|
||||
FaMobileAlt,
|
||||
FaServer,
|
||||
FaDatabase,
|
||||
FaChartBar,
|
||||
FaBookOpen,
|
||||
FaCreditCard,
|
||||
FaRegComment,
|
||||
FaPhone
|
||||
} from 'react-icons/fa';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { Helmet } from 'react-helmet'
|
||||
|
|
@ -24,42 +24,42 @@ const Home: React.FC = () => {
|
|||
|
||||
const features = [
|
||||
{
|
||||
icon: <Users className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaUsers className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.reliable'),
|
||||
description: translate('::Public.features.reliable.desc'),
|
||||
},
|
||||
{
|
||||
icon: <Calendar className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaCalendarAlt className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.rapid'),
|
||||
description: translate('::Public.features.rapid.desc'),
|
||||
},
|
||||
{
|
||||
icon: <BookOpen className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaBookOpen className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.expert'),
|
||||
description: translate('::Public.features.expert.desc'),
|
||||
},
|
||||
{
|
||||
icon: <CreditCard className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaCreditCard className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.muhasebe'),
|
||||
description: translate('::Public.features.muhasebe.desc'),
|
||||
},
|
||||
{
|
||||
icon: <MessageSquare className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaRegComment className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.iletisim'),
|
||||
description: translate('::Public.features.iletisim.desc'),
|
||||
},
|
||||
{
|
||||
icon: <Phone className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaPhone className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.mobil'),
|
||||
description: translate('::Public.features.mobil.desc'),
|
||||
},
|
||||
{
|
||||
icon: <BarChart className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaChartBar className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.scalable'),
|
||||
description: translate('::Public.features.scalable.desc'),
|
||||
},
|
||||
{
|
||||
icon: <Shield className="w-12 h-12 text-blue-500" />,
|
||||
icon: <FaShieldAlt className="w-12 h-12 text-blue-500" />,
|
||||
title: translate('::Public.features.guvenlik'),
|
||||
description: translate('::Public.features.guvenlik.desc'),
|
||||
},
|
||||
|
|
@ -67,25 +67,25 @@ const Home: React.FC = () => {
|
|||
|
||||
const solutions = [
|
||||
{
|
||||
icon: <Monitor className="w-16 h-16 text-white" />,
|
||||
icon: <FaDesktop className="w-16 h-16 text-white" />,
|
||||
title: translate('::Public.solutions.web.title'),
|
||||
description: translate('::Public.solutions.web.desc'),
|
||||
color: 'bg-blue-600',
|
||||
},
|
||||
{
|
||||
icon: <Smartphone className="w-16 h-16 text-white" />,
|
||||
icon: <FaMobileAlt className="w-16 h-16 text-white" />,
|
||||
title: translate('::Public.solutions.mobile.title'),
|
||||
description: translate('::Public.solutions.mobile.desc'),
|
||||
color: 'bg-purple-600',
|
||||
},
|
||||
{
|
||||
icon: <Server className="w-16 h-16 text-white" />,
|
||||
icon: <FaServer className="w-16 h-16 text-white" />,
|
||||
title: translate('::Public.solutions.custom.title'),
|
||||
description: translate('::Public.solutions.custom.desc'),
|
||||
color: 'bg-green-600',
|
||||
},
|
||||
{
|
||||
icon: <Database className="w-16 h-16 text-white" />,
|
||||
icon: <FaDatabase className="w-16 h-16 text-white" />,
|
||||
title: translate('::Public.solutions.database.title'),
|
||||
description: translate('::Public.solutions.database.desc'),
|
||||
color: 'bg-red-600',
|
||||
|
|
@ -128,7 +128,7 @@ const Home: React.FC = () => {
|
|||
className="inline-flex items-center justify-center px-8 py-4 bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white rounded-lg font-semibold transition-all transform hover:scale-105"
|
||||
>
|
||||
{translate('::Public.hero.cta.consultation')}{' '}
|
||||
<ArrowRight className="ml-2" size={20} />
|
||||
<FaArrowRight className="ml-2" size={20} />
|
||||
</Link>
|
||||
<Link
|
||||
to={ROUTES_ENUM.public.products}
|
||||
|
|
@ -140,21 +140,21 @@ const Home: React.FC = () => {
|
|||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-4xl mx-auto">
|
||||
<div className="bg-white/5 backdrop-blur-sm rounded-2xl p-8 text-center hover:scale-105 hover:bg-white/10 transition-all">
|
||||
<Calendar className="mx-auto mb-4 text-blue-400" size={40} />
|
||||
<FaCalendarAlt className="mx-auto mb-4 text-blue-400" size={40} />
|
||||
<h3 className="text-xl font-semibold mb-3 text-white">
|
||||
{translate('::Public.hero.service1.title')}
|
||||
</h3>
|
||||
<p className="text-gray-300">{translate('::Public.hero.service1.desc')}</p>
|
||||
</div>
|
||||
<div className="bg-white/5 backdrop-blur-sm rounded-2xl p-8 text-center hover:scale-105 hover:bg-white/10 transition-all">
|
||||
<Users className="mx-auto mb-4 text-purple-400" size={40} />
|
||||
<FaUsers className="mx-auto mb-4 text-purple-400" size={40} />
|
||||
<h3 className="text-xl font-semibold mb-3 text-white">
|
||||
{translate('::Public.hero.service2.title')}
|
||||
</h3>
|
||||
<p className="text-gray-300">{translate('::Public.hero.service2.desc')}</p>
|
||||
</div>
|
||||
<div className="bg-white/5 backdrop-blur-sm rounded-2xl p-8 text-center hover:scale-105 hover:bg-white/10 transition-all">
|
||||
<Shield className="mx-auto mb-4 text-indigo-400" size={40} />
|
||||
<FaShieldAlt className="mx-auto mb-4 text-indigo-400" size={40} />
|
||||
<h3 className="text-xl font-semibold mb-3 text-white">
|
||||
{translate('::Public.hero.service3.title')}
|
||||
</h3>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Frown } from 'lucide-react'; // Lucide-react kütüphanesinden Frown ikonunu import et
|
||||
import { FaFrown } from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization';
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ const NotFound: React.FC = () => {
|
|||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen bg-white text-gray-700 p-4"> {/* Arka plan ve metin rengi güncellendi, padding eklendi */}
|
||||
<Frown size={128} className="text-blue-600 mb-6" /> {/* İkon boyutu ve rengi güncellendi */}
|
||||
<FaFrown size={128} className="text-blue-600 mb-6" /> {/* İkon boyutu ve rengi güncellendi */}
|
||||
<h1 className="text-7xl font-bold text-gray-900 mb-4">404</h1> {/* Başlık boyutu ve rengi güncellendi */}
|
||||
<p className="text-xl text-gray-600 mb-8 text-center max-w-md"> {/* Metin rengi, margin ve max-width güncellendi */}
|
||||
{translate('::Public.notFound.message')}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { Code2, Globe2, Server, Users, Shield, Settings, CheckCircle } from 'lucide-react'
|
||||
import { FaCode, FaGlobe, FaServer, FaUsers, FaShieldAlt, FaCog, FaCheckCircle } from 'react-icons/fa';
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
|
@ -10,7 +10,7 @@ const Services: React.FC = () => {
|
|||
|
||||
const services = [
|
||||
{
|
||||
icon: <Code2 className="w-12 h-12 text-blue-600" />,
|
||||
icon: <FaCode className="w-12 h-12 text-blue-600" />,
|
||||
title: translate('::Public.services.software.title'),
|
||||
description: translate('::Public.services.software.desc'),
|
||||
features: [
|
||||
|
|
@ -22,7 +22,7 @@ const Services: React.FC = () => {
|
|||
],
|
||||
},
|
||||
{
|
||||
icon: <Users className="w-12 h-12 text-purple-600" />,
|
||||
icon: <FaUsers className="w-12 h-12 text-purple-600" />,
|
||||
title: translate('::Public.services.web.title'),
|
||||
description: translate('::Public.services.web.desc'),
|
||||
features: [
|
||||
|
|
@ -34,7 +34,7 @@ const Services: React.FC = () => {
|
|||
],
|
||||
},
|
||||
{
|
||||
icon: <Shield className="w-12 h-12 text-green-600" />,
|
||||
icon: <FaShieldAlt className="w-12 h-12 text-green-600" />,
|
||||
title: translate('::Public.services.mobile.title'),
|
||||
description: translate('::Public.services.mobile.desc'),
|
||||
features: [
|
||||
|
|
@ -46,7 +46,7 @@ const Services: React.FC = () => {
|
|||
],
|
||||
},
|
||||
{
|
||||
icon: <Server className="w-12 h-12 text-red-600" />,
|
||||
icon: <FaServer className="w-12 h-12 text-red-600" />,
|
||||
title: translate('::Public.services.database.title'),
|
||||
description: translate('::Public.services.database.desc'),
|
||||
features: [
|
||||
|
|
@ -58,7 +58,7 @@ const Services: React.FC = () => {
|
|||
],
|
||||
},
|
||||
{
|
||||
icon: <Globe2 className="w-12 h-12 text-yellow-600" />,
|
||||
icon: <FaGlobe className="w-12 h-12 text-yellow-600" />,
|
||||
title: translate('::Public.services.integration.title'),
|
||||
description: translate('::Public.services.integration.desc'),
|
||||
features: [
|
||||
|
|
@ -70,7 +70,7 @@ const Services: React.FC = () => {
|
|||
],
|
||||
},
|
||||
{
|
||||
icon: <Settings className="w-12 h-12 text-indigo-600" />,
|
||||
icon: <FaCog className="w-12 h-12 text-indigo-600" />,
|
||||
title: translate('::Public.services.consulting.title'),
|
||||
description: translate('::Public.services.consulting.desc'),
|
||||
features: [
|
||||
|
|
@ -189,7 +189,7 @@ const Services: React.FC = () => {
|
|||
<ul className="space-y-3 mb-8">
|
||||
{plan.features.map((feature, fIndex) => (
|
||||
<li key={fIndex} className="flex items-center space-x-2 text-gray-700">
|
||||
<CheckCircle className="w-5 h-5 text-green-500 flex-shrink-0" />
|
||||
<FaCheckCircle className="w-5 h-5 text-green-500 flex-shrink-0" />
|
||||
<span>{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Reference in a new issue