Developer Kit tasarım düzenlemesi
This commit is contained in:
parent
e8451627bd
commit
05b9f5f4a8
5 changed files with 179 additions and 169 deletions
|
|
@ -9613,12 +9613,6 @@
|
||||||
"en": "Props:",
|
"en": "Props:",
|
||||||
"tr": "Özellikler:"
|
"tr": "Özellikler:"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.DeveloperKit.Component.DateNotAvailable",
|
|
||||||
"en": "N/A",
|
|
||||||
"tr": "Yok"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.DeveloperKit.Component.Status.Active",
|
"key": "App.DeveloperKit.Component.Status.Active",
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import {
|
||||||
FaPaperPlane,
|
FaPaperPlane,
|
||||||
FaPlusCircle,
|
FaPlusCircle,
|
||||||
FaEdit,
|
FaEdit,
|
||||||
FaTrash
|
FaTrash,
|
||||||
} from 'react-icons/fa';
|
} from 'react-icons/fa'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface EndpointType {
|
interface EndpointType {
|
||||||
|
|
@ -372,9 +372,7 @@ const ApiManager: React.FC = () => {
|
||||||
<h1 className="text-2xl font-bold text-slate-900">
|
<h1 className="text-2xl font-bold text-slate-900">
|
||||||
{translate('::App.DeveloperKit.Endpoint.Title')}
|
{translate('::App.DeveloperKit.Endpoint.Title')}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-slate-600">
|
<p className="text-slate-600">{translate('::App.DeveloperKit.Endpoint.Description')}</p>
|
||||||
{translate('::App.DeveloperKit.Endpoint.Description')}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<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">
|
<div className="flex items-center gap-2 bg-blue-100 text-blue-700 px-3 py-1 rounded-full text-sm font-medium">
|
||||||
|
|
@ -385,16 +383,14 @@ const ApiManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Cards */}
|
{/* Stats Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-6 mb-8">
|
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-6 mb-4">
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-medium text-slate-600">
|
<p className="text-sm font-medium text-slate-600">
|
||||||
{translate('::App.DeveloperKit.Endpoint.GeneratedCrud')}
|
{translate('::App.DeveloperKit.Endpoint.GeneratedCrud')}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-2xl font-bold text-slate-900 mt-1">
|
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.generated}</p>
|
||||||
{stats.generated}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-emerald-100 text-emerald-600 p-3 rounded-lg">
|
<div className="bg-emerald-100 text-emerald-600 p-3 rounded-lg">
|
||||||
<FaDatabase className="w-6 h-6" />
|
<FaDatabase className="w-6 h-6" />
|
||||||
|
|
@ -456,42 +452,40 @@ const ApiManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Filters */}
|
{/* Filters */}
|
||||||
<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 flex-col lg:flex-row gap-4">
|
<div className="flex-1 relative">
|
||||||
<div className="flex-1 relative">
|
<FaSearch 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
|
||||||
<input
|
type="text"
|
||||||
type="text"
|
placeholder={translate('::App.DeveloperKit.Endpoint.SearchPlaceholder')}
|
||||||
placeholder={translate('::App.DeveloperKit.Endpoint.SearchPlaceholder')}
|
value={searchTerm}
|
||||||
value={searchTerm}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
||||||
className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div className="flex items-center gap-4">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex items-center gap-2">
|
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
<select
|
||||||
<select
|
value={filterMethod}
|
||||||
value={filterMethod}
|
onChange={(e) =>
|
||||||
onChange={(e) =>
|
setFilterMethod(e.target.value as 'all' | 'GET' | 'POST' | 'PUT' | 'DELETE')
|
||||||
setFilterMethod(e.target.value as 'all' | 'GET' | 'POST' | 'PUT' | 'DELETE')
|
}
|
||||||
}
|
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
||||||
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
>
|
||||||
>
|
<option value="all">{translate('::App.DeveloperKit.Endpoint.AllMethods')}</option>
|
||||||
<option value="all">{translate('::App.DeveloperKit.Endpoint.AllMethods')}</option>
|
<option value="GET">GET</option>
|
||||||
<option value="GET">GET</option>
|
<option value="POST">POST</option>
|
||||||
<option value="POST">POST</option>
|
<option value="PUT">PUT</option>
|
||||||
<option value="PUT">PUT</option>
|
<option value="DELETE">DELETE</option>
|
||||||
<option value="DELETE">DELETE</option>
|
</select>
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Endpoints List */}
|
{/* Endpoints List */}
|
||||||
{filteredEndpoints.length > 0 ? (
|
{filteredEndpoints.length > 0 ? (
|
||||||
<div className="space-y-4">
|
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6">
|
||||||
{filteredEndpoints.map((endpoint) => (
|
{filteredEndpoints.map((endpoint) => (
|
||||||
<div
|
<div
|
||||||
key={endpoint.id}
|
key={endpoint.id}
|
||||||
|
|
@ -508,6 +502,7 @@ const ApiManager: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
{/* Sol taraf */}
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span
|
<span
|
||||||
className={`px-3 py-1 text-sm font-medium rounded-full border ${getMethodColor(
|
className={`px-3 py-1 text-sm font-medium rounded-full border ${getMethodColor(
|
||||||
|
|
@ -522,19 +517,25 @@ const ApiManager: React.FC = () => {
|
||||||
{endpoint.path}
|
{endpoint.path}
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
</div>
|
||||||
{endpoint.type === 'generated' && (
|
|
||||||
<span className="bg-emerald-100 text-emerald-700 text-xs px-2 py-1 rounded-full">
|
{/* Sağ taraf */}
|
||||||
{translate('::App.DeveloperKit.Endpoint.AutoGenerated')}
|
<div className="flex items-center gap-3">
|
||||||
</span>
|
{endpoint.type === 'generated' && (
|
||||||
)}
|
<span className="bg-emerald-100 text-emerald-700 text-xs px-2 py-1 rounded-full">
|
||||||
|
{translate('::App.DeveloperKit.Endpoint.AutoGenerated')}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<FaCheckCircle className="w-5 h-5 text-green-500" />
|
||||||
|
<span className="text-sm text-slate-500">
|
||||||
|
{translate('::App.DeveloperKit.Endpoint.Active')}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<FaCheckCircle className="w-5 h-5 text-green-500" />
|
|
||||||
<span className="text-sm text-slate-500">{translate('::App.DeveloperKit.Endpoint.Active')}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{endpoint.description && (
|
{endpoint.description && (
|
||||||
<p className="text-slate-600 text-sm mt-2">{endpoint.description}</p>
|
<p className="text-slate-600 text-sm mt-2">{endpoint.description}</p>
|
||||||
)}
|
)}
|
||||||
|
|
@ -543,10 +544,12 @@ const ApiManager: React.FC = () => {
|
||||||
{/* Expanded Details */}
|
{/* Expanded Details */}
|
||||||
{selectedEndpoint === endpoint.id && (
|
{selectedEndpoint === endpoint.id && (
|
||||||
<div className="border-t border-slate-200 p-6 bg-slate-50">
|
<div className="border-t border-slate-200 p-6 bg-slate-50">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 gap-6">
|
||||||
{/* Request Details */}
|
{/* Request Details */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-semibold text-slate-900 mb-3">{translate('::App.DeveloperKit.Endpoint.RequestTitle')}</h4>
|
<h4 className="font-semibold text-slate-900 mb-3">
|
||||||
|
{translate('::App.DeveloperKit.Endpoint.RequestTitle')}
|
||||||
|
</h4>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
<label className="block text-sm font-medium text-slate-700 mb-1">
|
||||||
|
|
@ -627,7 +630,9 @@ const ApiManager: React.FC = () => {
|
||||||
<textarea
|
<textarea
|
||||||
value={getCurrentRequestBody(endpoint)}
|
value={getCurrentRequestBody(endpoint)}
|
||||||
onChange={(e) => updateRequestBody(endpoint.id, e.target.value)}
|
onChange={(e) => updateRequestBody(endpoint.id, e.target.value)}
|
||||||
placeholder={translate('::App.DeveloperKit.Endpoint.RequestBodyPlaceholder')}
|
placeholder={translate(
|
||||||
|
'::App.DeveloperKit.Endpoint.RequestBodyPlaceholder',
|
||||||
|
)}
|
||||||
rows={8}
|
rows={8}
|
||||||
className="w-full px-3 py-2 text-sm border border-slate-300 rounded font-mono focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-2 text-sm border border-slate-300 rounded font-mono focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
/>
|
/>
|
||||||
|
|
@ -672,7 +677,9 @@ const ApiManager: React.FC = () => {
|
||||||
|
|
||||||
{/* Test Section */}
|
{/* Test Section */}
|
||||||
<div className="bg-white border border-slate-300 rounded p-4">
|
<div className="bg-white border border-slate-300 rounded p-4">
|
||||||
<h5 className="font-medium text-slate-900 mb-3">{translate('::App.DeveloperKit.Endpoint.TestSectionTitle')}</h5>
|
<h5 className="font-medium text-slate-900 mb-3">
|
||||||
|
{translate('::App.DeveloperKit.Endpoint.TestSectionTitle')}
|
||||||
|
</h5>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => testEndpoint(endpoint)}
|
onClick={() => testEndpoint(endpoint)}
|
||||||
|
|
@ -684,7 +691,9 @@ const ApiManager: React.FC = () => {
|
||||||
) : (
|
) : (
|
||||||
<FaPaperPlane 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')}
|
{loadingEndpoints.has(endpoint.id)
|
||||||
|
? translate('::App.DeveloperKit.Endpoint.SendLoading')
|
||||||
|
: translate('::App.DeveloperKit.Endpoint.SendRequest')}
|
||||||
</button>
|
</button>
|
||||||
{testResults[endpoint.id] && (
|
{testResults[endpoint.id] && (
|
||||||
<button
|
<button
|
||||||
|
|
@ -716,7 +725,8 @@ const ApiManager: React.FC = () => {
|
||||||
<FaExclamationCircle className="w-5 h-5 text-red-500" />
|
<FaExclamationCircle className="w-5 h-5 text-red-500" />
|
||||||
)}
|
)}
|
||||||
<h5 className="font-semibold text-slate-900">
|
<h5 className="font-semibold text-slate-900">
|
||||||
{translate('::App.DeveloperKit.Endpoint.TestResultLabel')} ({testResults[endpoint.id].status})
|
{translate('::App.DeveloperKit.Endpoint.TestResultLabel')} (
|
||||||
|
{testResults[endpoint.id].status})
|
||||||
</h5>
|
</h5>
|
||||||
<span className="text-xs text-slate-500">
|
<span className="text-xs text-slate-500">
|
||||||
{new Date(testResults[endpoint.id].timestamp).toLocaleTimeString()}
|
{new Date(testResults[endpoint.id].timestamp).toLocaleTimeString()}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ const ComponentManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Statistics Cards */}
|
{/* Statistics Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-4">
|
||||||
{stats.map((stat, index) => (
|
{stats.map((stat, index) => (
|
||||||
<div key={index} className="bg-white rounded-lg border border-slate-200 p-6">
|
<div key={index} className="bg-white rounded-lg border border-slate-200 p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -123,34 +123,32 @@ const ComponentManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Filters */}
|
{/* Filters */}
|
||||||
<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 flex-col sm:flex-row gap-4">
|
<div className="flex-1 relative">
|
||||||
<div className="flex-1 relative">
|
<FaSearch 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
|
||||||
<input
|
type="text"
|
||||||
type="text"
|
placeholder={translate('::App.DeveloperKit.Component.SearchPlaceholder')}
|
||||||
placeholder={translate('::App.DeveloperKit.Component.SearchPlaceholder')}
|
value={searchTerm}
|
||||||
value={searchTerm}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex items-center gap-2">
|
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
<select
|
||||||
<select
|
value={filterActive}
|
||||||
value={filterActive}
|
onChange={(e) => setFilterActive(e.target.value as 'all' | 'active' | 'inactive')}
|
||||||
onChange={(e) => setFilterActive(e.target.value as 'all' | 'active' | 'inactive')}
|
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
>
|
||||||
>
|
<option value="all">{translate('::App.DeveloperKit.Component.Filter.All')}</option>
|
||||||
<option value="all">{translate('::App.DeveloperKit.Component.Filter.All')}</option>
|
<option value="active">
|
||||||
<option value="active">
|
{translate('::App.DeveloperKit.Component.Filter.Active')}
|
||||||
{translate('::App.DeveloperKit.Component.Filter.Active')}
|
</option>
|
||||||
</option>
|
<option value="inactive">
|
||||||
<option value="inactive">
|
{translate('::App.DeveloperKit.Component.Filter.Inactive')}
|
||||||
{translate('::App.DeveloperKit.Component.Filter.Inactive')}
|
</option>
|
||||||
</option>
|
</select>
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -162,14 +160,15 @@ const ComponentManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : filteredComponents?.length > 0 ? (
|
) : filteredComponents?.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-6">
|
||||||
{filteredComponents.map((component) => (
|
{filteredComponents.map((component) => (
|
||||||
<div
|
<div
|
||||||
key={component.id}
|
key={component.id}
|
||||||
className="bg-white rounded-lg border border-slate-200 shadow-sm hover:shadow-md transition-shadow"
|
className="bg-white rounded-lg border border-slate-200 shadow-sm hover:shadow-md transition-shadow"
|
||||||
>
|
>
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
<div className="flex items-start justify-between mb-4">
|
<div className="flex items-start justify-between">
|
||||||
|
{/* Sol taraf */}
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<h3 className="text-lg font-semibold text-slate-900">{component.name}</h3>
|
<h3 className="text-lg font-semibold text-slate-900">{component.name}</h3>
|
||||||
|
|
@ -179,6 +178,7 @@ const ComponentManager: React.FC = () => {
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-slate-600 text-sm mb-3">
|
<p className="text-slate-600 text-sm mb-3">
|
||||||
{(() => {
|
{(() => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -195,17 +195,17 @@ const ComponentManager: React.FC = () => {
|
||||||
{component.description && (
|
{component.description && (
|
||||||
<p className="text-slate-600 text-sm mb-3">{component.description}</p>
|
<p className="text-slate-600 text-sm mb-3">{component.description}</p>
|
||||||
)}
|
)}
|
||||||
<div className="flex items-center gap-4 text-xs text-slate-500">
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<FaCalendarAlt className="w-3 h-3" />
|
|
||||||
<span>
|
|
||||||
{component.lastModificationTime
|
|
||||||
? new Date(component.lastModificationTime).toLocaleDateString()
|
|
||||||
: translate('::App.DeveloperKit.Component.DateNotAvailable')}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Sağ taraf */}
|
||||||
|
{component.lastModificationTime && (
|
||||||
|
<div className="flex items-center gap-1 text-xs text-slate-500 ml-4 whitespace-nowrap">
|
||||||
|
<FaCalendarAlt className="w-3 h-3" />
|
||||||
|
<span>
|
||||||
|
{new Date(component.lastModificationTime).toLocaleDateString() ?? ''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Props Preview */}
|
{/* Props Preview */}
|
||||||
|
|
@ -221,7 +221,7 @@ const ComponentManager: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<div className="flex items-center justify-between pt-4 border-t border-slate-100">
|
<div className="flex items-center justify-between pt-2 border-t border-slate-100">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleToggleActive(component.id, !component.isActive)}
|
onClick={() => handleToggleActive(component.id, !component.isActive)}
|
||||||
|
|
@ -281,7 +281,7 @@ const ComponentManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
<div className="max-w-md mx-auto">
|
<div className="mx-auto">
|
||||||
<div className="bg-slate-100 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
<div className="bg-slate-100 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||||
<FaPlus className="w-8 h-8 text-slate-500" />
|
<FaPlus className="w-8 h-8 text-slate-500" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ const Dashboard: React.FC = () => {
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-4">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -198,16 +198,16 @@ const Dashboard: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Grid */}
|
{/* Stats Grid */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
{stats.map((stat) => {
|
{stats.map((stat) => {
|
||||||
const Icon = stat.icon
|
const Icon = stat.icon
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
key={stat.name}
|
key={stat.name}
|
||||||
to={stat.href}
|
to={stat.href}
|
||||||
className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 hover:shadow-md transition-all duration-200 group"
|
className="bg-white rounded-xl shadow-sm border border-slate-200 p-4 hover:shadow-md transition-all duration-200 group"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between">
|
||||||
<div
|
<div
|
||||||
className={`${stat.bgColor} ${stat.color} p-3 rounded-lg group-hover:scale-110 transition-transform`}
|
className={`${stat.bgColor} ${stat.color} p-3 rounded-lg group-hover:scale-110 transition-transform`}
|
||||||
>
|
>
|
||||||
|
|
@ -228,20 +228,20 @@ const Dashboard: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Development Flow */}
|
{/* Development Flow */}
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-8">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-4">
|
||||||
<div className="flex items-center gap-2 mb-6">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<FaCog 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">
|
<h2 className="text-xl font-semibold text-slate-900">
|
||||||
{translate('::App.DeveloperKit.Dashboard.Flow.Title')}
|
{translate('::App.DeveloperKit.Dashboard.Flow.Title')}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-5 gap-8">
|
||||||
{developmentFlow.map((flow, index) => {
|
{developmentFlow.map((flow, index) => {
|
||||||
const Icon = flow.icon
|
const Icon = flow.icon
|
||||||
return (
|
return (
|
||||||
<Link key={flow.step} to={flow.href} className="group relative">
|
<Link key={flow.step} to={flow.href} className="group relative">
|
||||||
<div
|
<div
|
||||||
className={`${flow.color} text-white p-6 rounded-lg transition-all duration-200 transform group-hover:scale-105`}
|
className={`${flow.color} text-white p-4 rounded-lg transition-all duration-200 transform group-hover:scale-105`}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<div className="bg-white bg-opacity-20 rounded-lg p-2">
|
<div className="bg-white bg-opacity-20 rounded-lg p-2">
|
||||||
|
|
@ -252,7 +252,7 @@ const Dashboard: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="font-semibold text-lg mb-2 text-white">{flow.title}</h3>
|
<h3 className="font-semibold text-lg mb-2 text-white">{flow.title}</h3>
|
||||||
<p className="text-sm opacity-90">{flow.description}</p>
|
<p className="text-xs opacity-90">{flow.description}</p>
|
||||||
|
|
||||||
{flow.status === 'action-needed' && (
|
{flow.status === 'action-needed' && (
|
||||||
<div className="absolute -top-2 -right-2">
|
<div className="absolute -top-2 -right-2">
|
||||||
|
|
@ -274,9 +274,9 @@ const Dashboard: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
|
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
||||||
{/* System Health */}
|
{/* System Health */}
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-4">
|
||||||
<div className="flex items-center gap-2 mb-4">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<FaCog 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">
|
<h3 className="text-lg font-semibold text-slate-900">
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ const MigrationManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Cards */}
|
{/* Stats Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -196,7 +196,7 @@ const MigrationManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-medium text-slate-600">
|
<p className="text-sm font-medium text-slate-600">
|
||||||
|
|
@ -209,7 +209,7 @@ const MigrationManager: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-medium text-slate-600">
|
<p className="text-sm font-medium text-slate-600">
|
||||||
|
|
@ -239,19 +239,19 @@ const MigrationManager: React.FC = () => {
|
||||||
|
|
||||||
{/* Entities Needing Migration */}
|
{/* Entities Needing Migration */}
|
||||||
{entitiesNeedingMigration.length > 0 && (
|
{entitiesNeedingMigration.length > 0 && (
|
||||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-6 mb-6">
|
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-4">
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<div className="bg-yellow-100 rounded-lg p-2">
|
<div className="bg-yellow-100 rounded-lg p-2">
|
||||||
<FaBolt className="w-6 h-6 text-yellow-600" />
|
<FaBolt className="w-6 h-6 text-yellow-600" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 className="text-lg font-semibold text-slate-900 mb-2">
|
<h3 className="text-lg font-semibold text-slate-900">
|
||||||
{translate('::App.DeveloperKit.Migration.EntitiesRequireMigration')}
|
{translate('::App.DeveloperKit.Migration.EntitiesRequireMigration')}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-slate-700 mb-4">
|
<p className="text-slate-700 mb-2">
|
||||||
{translate('::App.DeveloperKit.Migration.EntitiesRequireMigrationDescription')}
|
{translate('::App.DeveloperKit.Migration.EntitiesRequireMigrationDescription')}
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-3">
|
||||||
{entitiesNeedingMigration.map((entity) => (
|
{entitiesNeedingMigration.map((entity) => (
|
||||||
<div key={entity.id} className="bg-white border border-yellow-300 rounded-lg p-4">
|
<div key={entity.id} className="bg-white border border-yellow-300 rounded-lg p-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -280,41 +280,39 @@ const MigrationManager: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Filters */}
|
{/* Filters */}
|
||||||
<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 flex-col lg:flex-row gap-4">
|
<div className="flex-1 relative">
|
||||||
<div className="flex-1 relative">
|
<FaSearch 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
|
||||||
<input
|
type="text"
|
||||||
type="text"
|
placeholder={translate('::App.DeveloperKit.Migration.SearchPlaceholder')}
|
||||||
placeholder={translate('::App.DeveloperKit.Migration.SearchPlaceholder')}
|
value={searchTerm}
|
||||||
value={searchTerm}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
||||||
className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div className="flex items-center gap-4">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex items-center gap-2">
|
<FaFilter className="w-5 h-5 text-slate-500" />
|
||||||
<FaFilter className="w-5 h-5 text-slate-500" />
|
<select
|
||||||
<select
|
value={filterStatus}
|
||||||
value={filterStatus}
|
onChange={(e) =>
|
||||||
onChange={(e) =>
|
setFilterStatus(e.target.value as 'all' | 'pending' | 'applied' | 'failed')
|
||||||
setFilterStatus(e.target.value as 'all' | 'pending' | 'applied' | 'failed')
|
}
|
||||||
}
|
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
||||||
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
|
>
|
||||||
>
|
<option value="all">{translate('::App.DeveloperKit.Migration.AllStatus')}</option>
|
||||||
<option value="all">{translate('::App.DeveloperKit.Migration.AllStatus')}</option>
|
<option value="pending">Pending</option>
|
||||||
<option value="pending">Pending</option>
|
<option value="applied">Applied</option>
|
||||||
<option value="applied">Applied</option>
|
<option value="failed">Failed</option>
|
||||||
<option value="failed">Failed</option>
|
</select>
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Migrations List */}
|
{/* Migrations List */}
|
||||||
{filteredMigrations.length > 0 ? (
|
{filteredMigrations.length > 0 ? (
|
||||||
<div className="space-y-4">
|
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6">
|
||||||
{filteredMigrations.map((migration) => {
|
{filteredMigrations.map((migration) => {
|
||||||
const StatusIcon = getStatusIcon(migration.status)
|
const StatusIcon = getStatusIcon(migration.status)
|
||||||
return (
|
return (
|
||||||
|
|
@ -324,25 +322,33 @@ const MigrationManager: React.FC = () => {
|
||||||
>
|
>
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
<div className="flex items-start justify-between mb-4">
|
<div className="flex items-start justify-between mb-4">
|
||||||
<div className="flex-1">
|
{/* Sol taraf */}
|
||||||
<div className="flex items-center gap-3 mb-2">
|
<div className="flex items-center gap-3">
|
||||||
<div className="bg-blue-100 text-blue-600 p-2 rounded-lg">
|
<div className="bg-blue-100 text-blue-600 p-2 rounded-lg">
|
||||||
<FaDatabase className="w-5 h-5" />
|
<FaDatabase className="w-5 h-5" />
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-slate-900">
|
|
||||||
{migration.fileName || `Migration for ${migration.entityName}`}
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-slate-600">Entity: {migration.entityName}</p>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
className={`px-3 py-1 text-sm font-medium rounded-full border ${getStatusColor(migration.status)}`}
|
|
||||||
>
|
|
||||||
<StatusIcon className="w-4 h-4 inline mr-1" />
|
|
||||||
{migration.status.charAt(0).toUpperCase() + migration.status.slice(1)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4 text-xs text-slate-500">
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold text-slate-900">
|
||||||
|
{migration.fileName || `Migration for ${migration.entityName}`}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-slate-600">Entity: {migration.entityName}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sağ taraf */}
|
||||||
|
<div className="flex flex-col items-end gap-2 text-right">
|
||||||
|
{/* Status etiketi */}
|
||||||
|
<span
|
||||||
|
className={`px-3 py-1 text-sm font-medium rounded-full border ${getStatusColor(
|
||||||
|
migration.status,
|
||||||
|
)}`}
|
||||||
|
>
|
||||||
|
<StatusIcon className="w-4 h-4 inline mr-1" />
|
||||||
|
{migration.status.charAt(0).toUpperCase() + migration.status.slice(1)}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* Tarihler */}
|
||||||
|
<div className="flex flex-col items-end text-xs text-slate-500">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<FaCalendarAlt className="w-3 h-3" />
|
<FaCalendarAlt className="w-3 h-3" />
|
||||||
<span>
|
<span>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue