146 lines
6.4 KiB
TypeScript
146 lines
6.4 KiB
TypeScript
'use client'
|
||
|
||
import { useActionState, useState } from 'react'
|
||
import Link from 'next/link'
|
||
import { createLicenseAction, type CreateLicenseState } from '../actions'
|
||
import type { CustomerOption } from '@/lib/supabaseAdmin'
|
||
|
||
const initialState: CreateLicenseState = {}
|
||
|
||
export default function NewLicenseForm({ customers }: { customers: CustomerOption[] }) {
|
||
const [state, formAction, pending] = useActionState(createLicenseAction, initialState)
|
||
const [copied, setCopied] = useState(false)
|
||
|
||
if (state.result) {
|
||
const { id, licenseKey } = state.result
|
||
return (
|
||
<div className="rounded-lg bg-white dark:bg-gray-950 border border-gray-200 dark:border-gray-800 shadow-sm p-6 space-y-5">
|
||
<div className="rounded-md bg-amber-50 dark:bg-amber-950/40 border border-amber-200 dark:border-amber-900 px-4 py-3 text-sm text-amber-800 dark:text-amber-400">
|
||
Bu anahtar bir daha gösterilmeyecek — şimdi kopyalayıp müşteriye iletin.
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Lisans Anahtarı</label>
|
||
<div className="flex items-center gap-2">
|
||
<code className="flex-1 rounded-md border border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 px-3 py-2 text-lg font-mono tracking-wider text-gray-900 dark:text-white">
|
||
{licenseKey}
|
||
</code>
|
||
<button
|
||
type="button"
|
||
onClick={() => {
|
||
navigator.clipboard.writeText(licenseKey)
|
||
setCopied(true)
|
||
setTimeout(() => setCopied(false), 2000)
|
||
}}
|
||
className="rounded-md bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-medium px-4 py-2 transition-colors whitespace-nowrap"
|
||
>
|
||
{copied ? 'Kopyalandı ✓' : 'Kopyala'}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-3 pt-2">
|
||
<Link href={`/admin/licenses/${id}`} className="rounded-md bg-gray-900 hover:bg-gray-800 dark:bg-white dark:hover:bg-gray-200 text-white dark:text-gray-900 text-sm font-medium px-4 py-2 transition-colors">
|
||
Lisans Detayına Git
|
||
</Link>
|
||
<Link href="/admin/licenses" className="text-sm text-gray-500 hover:text-gray-900 dark:hover:text-white">
|
||
Lisanslara Dön
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<form action={formAction} className="rounded-lg bg-white dark:bg-gray-950 border border-gray-200 dark:border-gray-800 shadow-sm p-6 space-y-5">
|
||
{state.error && (
|
||
<div className="rounded-md bg-red-50 dark:bg-red-950/40 border border-red-200 dark:border-red-900 px-4 py-3 text-sm text-red-700 dark:text-red-400">
|
||
{state.error}
|
||
</div>
|
||
)}
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Müşteri (opsiyonel)</label>
|
||
<select
|
||
name="customer_email"
|
||
defaultValue=""
|
||
className="w-full rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||
>
|
||
<option value="">— Bağlantı yok —</option>
|
||
{customers.map((c) => (
|
||
<option key={c.id} value={c.email}>
|
||
{c.name || '(isimsiz)'} — {c.email}
|
||
</option>
|
||
))}
|
||
</select>
|
||
<p className="mt-1 text-xs text-gray-400">Kullanıcılar listesinden seçin. Boş bırakırsanız sonra da eşleştirebilirsiniz.</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Plan</label>
|
||
<input
|
||
type="text"
|
||
name="plan"
|
||
defaultValue="professional"
|
||
list="plan-options"
|
||
className="w-full rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||
/>
|
||
<datalist id="plan-options">
|
||
<option value="trial" />
|
||
<option value="starter" />
|
||
<option value="professional" />
|
||
<option value="enterprise" />
|
||
</datalist>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Durum</label>
|
||
<select
|
||
name="status"
|
||
defaultValue="active"
|
||
className="w-full rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||
>
|
||
<option value="active">active</option>
|
||
<option value="expired">expired</option>
|
||
<option value="revoked">revoked</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Maks. Cihaz</label>
|
||
<input
|
||
type="number"
|
||
name="max_devices"
|
||
min={1}
|
||
defaultValue={2}
|
||
className="w-full rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Bitiş Tarihi (opsiyonel)</label>
|
||
<input
|
||
type="date"
|
||
name="expires_at"
|
||
className="w-full rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-3 pt-2">
|
||
<button
|
||
type="submit"
|
||
disabled={pending}
|
||
className="rounded-md bg-indigo-600 hover:bg-indigo-700 disabled:opacity-60 text-white text-sm font-medium px-4 py-2 transition-colors"
|
||
>
|
||
{pending ? 'Oluşturuluyor...' : 'Lisans Oluştur'}
|
||
</button>
|
||
<Link href="/admin/licenses" className="text-sm text-gray-500 hover:text-gray-900 dark:hover:text-white">
|
||
Vazgeç
|
||
</Link>
|
||
</div>
|
||
</form>
|
||
)
|
||
}
|