feat: move runtime selection to Step 0, hide source code for WordPress

- Move Application Type (Node.js/Laravel/WordPress) cards from Step 1 to Step 0 (Basic Info)
- Hide source code upload/git section when WordPress is selected
- Show WordPress info box explaining official Docker image usage
- Rename Step 1 heading to 'Versions & Database'
- Update Review step to show 'WordPress (Official Image)' as source
- Hide git branch/token review lines for WordPress
This commit is contained in:
keyhan
2026-04-07 00:47:42 +03:30
parent 762657f9ed
commit e775b57421
2 changed files with 62 additions and 39 deletions
+59 -36
View File
@@ -9,7 +9,7 @@ import { toast } from 'react-toastify';
import type { CreateApplicationDto, ClusterPublic, ClusterPoolPublic } from '@/types';
import { Hexagon, FolderUp, Link as LinkIcon, CheckCircle, Package, Server, Scale, Home, Target, BarChart3, RotateCw, KeyRound, Rocket, Clock, Upload, XCircle, Database, Eye, EyeOff, RefreshCw } from 'lucide-react';
const steps = ['Basic Info', 'Runtime & Database', 'Resources', 'Review'];
const steps = ['Basic Info', 'Versions & Database', 'Resources', 'Review'];
export default function DeployPage() {
const router = useRouter();
@@ -157,8 +157,11 @@ export default function DeployPage() {
const canNext = () => {
if (step === 0) {
if (form.name.length < 2) return false;
// WordPress doesn't require source code
if (form.runtime !== 'wordpress') {
if (sourceMethod === 'upload' && !zipFile) return false;
if (sourceMethod === 'git' && !form.gitUrl) return false;
}
return true;
}
return true;
@@ -226,7 +229,39 @@ export default function DeployPage() {
/>
</div>
{/* Source Code Method */}
{/* Application Runtime */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-3">Application Type</label>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{[
{ value: 'nodejs', label: 'Node.js', icon: <Hexagon className="w-6 h-6 text-green-500" />, desc: 'Express, NestJS, Fastify...' },
{ value: 'laravel', label: 'Laravel', icon: <Hexagon className="w-6 h-6 text-orange-500" />, desc: 'PHP, Composer, Artisan' },
{ value: 'wordpress', label: 'WordPress', icon: <Hexagon className="w-6 h-6 text-blue-600" />, desc: 'Official image, wp-content' },
].map((opt) => (
<button
key={opt.value}
type="button"
onClick={() => {
const updates: any = { runtime: opt.value as any, phpVersion: '' };
if (opt.value === 'nodejs') { updates.port = 3000; updates.runtimeVersion = '20'; }
else if (opt.value === 'laravel') { updates.port = 8000; updates.runtimeVersion = ''; updates.phpVersion = '8.3'; }
else if (opt.value === 'wordpress') { updates.port = 80; updates.databaseType = 'mysql'; updates.runtimeVersion = '6.7'; updates.phpVersion = '8.3'; }
setForm({ ...form, ...updates });
}}
className={`p-4 rounded-xl border-2 text-left transition-colors ${
form.runtime === opt.value ? 'border-primary-500 bg-primary-50' : 'border-gray-200 hover:border-gray-300'
}`}
>
{opt.icon}
<p className="mt-2 font-semibold text-gray-900">{opt.label}</p>
<p className="text-xs text-gray-500">{opt.desc}</p>
</button>
))}
</div>
</div>
{/* Source Code Method — hidden for WordPress */}
{form.runtime !== 'wordpress' && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-3">Source Code</label>
<div className="grid grid-cols-2 gap-3 mb-4">
@@ -357,42 +392,28 @@ export default function DeployPage() {
</div>
)}
</div>
)}
{/* WordPress info — shown when WordPress is selected */}
{form.runtime === 'wordpress' && (
<div className="p-4 bg-blue-50/50 border border-blue-200 rounded-xl">
<div className="flex items-center gap-2 mb-2">
<Hexagon className="w-5 h-5 text-blue-600" />
<h3 className="text-sm font-semibold text-gray-800">WordPress (Official Image)</h3>
</div>
<p className="text-xs text-gray-500">
وردپرس از ایمیج رسمی Docker استفاده میکند و نیازی به آپلود سورسکد ندارد.
قالبها و افزونهها از طریق پنل مدیریت وردپرس نصب میشوند.
</p>
</div>
)}
</div>
)}
{/* Step 1: Runtime & Database */}
{/* Step 1: Versions & Database */}
{step === 1 && (
<div className="space-y-6">
<h2 className="text-lg font-semibold text-gray-900">Runtime & Database</h2>
<div>
<label className="block text-sm font-medium text-gray-700 mb-3">Application Runtime</label>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{[
{ value: 'nodejs', label: 'Node.js', icon: <Hexagon className="w-6 h-6 text-green-500" />, desc: 'Express, NestJS, Fastify...' },
{ value: 'laravel', label: 'Laravel', icon: <Hexagon className="w-6 h-6 text-orange-500" />, desc: 'PHP, Composer, Artisan' },
{ value: 'wordpress', label: 'WordPress', icon: <Hexagon className="w-6 h-6 text-blue-600" />, desc: 'PHP, Apache, wp-content' },
].map((opt) => (
<button
key={opt.value}
type="button"
onClick={() => {
const updates: any = { runtime: opt.value as any, phpVersion: '' };
if (opt.value === 'nodejs') { updates.port = 3000; updates.runtimeVersion = '20'; }
else if (opt.value === 'laravel') { updates.port = 8000; updates.runtimeVersion = ''; updates.phpVersion = '8.3'; }
else if (opt.value === 'wordpress') { updates.port = 80; updates.databaseType = 'mysql'; updates.runtimeVersion = '6.7'; updates.phpVersion = '8.3'; }
setForm({ ...form, ...updates });
}}
className={`p-4 rounded-xl border-2 text-left transition-colors ${
form.runtime === opt.value ? 'border-primary-500 bg-primary-50' : 'border-gray-200 hover:border-gray-300'
}`}
>
{opt.icon}
<p className="mt-2 font-semibold text-gray-900">{opt.label}</p>
<p className="text-xs text-gray-500">{opt.desc}</p>
</button>
))}
</div>
</div>
<h2 className="text-lg font-semibold text-gray-900">Versions & Database</h2>
{/* Runtime Version Selectors */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
@@ -954,20 +975,22 @@ export default function DeployPage() {
<div className="flex justify-between">
<span className="text-sm text-gray-500">Source</span>
<span className="text-sm font-medium">
{sourceMethod === 'upload'
{form.runtime === 'wordpress'
? 'WordPress (Official Image)'
: sourceMethod === 'upload'
? zipFile
? zipFile.name
: '—'
: form.gitUrl || '—'}
</span>
</div>
{sourceMethod === 'git' && form.gitBranch && (
{form.runtime !== 'wordpress' && sourceMethod === 'git' && form.gitBranch && (
<div className="flex justify-between">
<span className="text-sm text-gray-500">Branch</span>
<span className="text-sm font-medium">{form.gitBranch}</span>
</div>
)}
{sourceMethod === 'git' && form.gitToken && (
{form.runtime !== 'wordpress' && sourceMethod === 'git' && form.gitToken && (
<div className="flex justify-between">
<span className="text-sm text-gray-500">Auth</span>
<span className="text-sm font-medium text-green-600">Token provided</span>
File diff suppressed because one or more lines are too long