497 lines
22 KiB
TypeScript
497 lines
22 KiB
TypeScript
import { getTenantByNameDetail } from '@/services/tenant.service'
|
||
import { CustomTenantDto } from '@/proxy/config/models'
|
||
import {
|
||
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'
|
||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||
|
||
interface TenantFormProps {
|
||
onSubmit: (tenant: CustomTenantDto) => void
|
||
onBack: () => void
|
||
}
|
||
|
||
export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
||
const [isExisting, setIsExisting] = useState<boolean>(true)
|
||
const [formData, setFormData] = useState<Partial<CustomTenantDto>>({})
|
||
const navigate = useNavigate()
|
||
const { translate } = useLocalization()
|
||
|
||
const handleSubmit = (e: React.FormEvent) => {
|
||
e.preventDefault()
|
||
onSubmit({ ...formData, isExisting: isExisting! } as CustomTenantDto)
|
||
}
|
||
|
||
const handleInputChange = (field: keyof CustomTenantDto, value: string) => {
|
||
setFormData((prev) => ({ ...prev, [field]: value }))
|
||
}
|
||
|
||
const getTenantInfo = async () => {
|
||
if (!formData.name) return
|
||
try {
|
||
const tenant = await getTenantByNameDetail(formData.name)
|
||
|
||
setFormData((prev) => ({
|
||
...prev,
|
||
id: tenant.data.id,
|
||
name: tenant.data.name,
|
||
isActive: tenant.data.isActive,
|
||
organizationName: tenant.data.organizationName,
|
||
founder: tenant.data.founder,
|
||
vknTckn: tenant.data.vknTckn,
|
||
taxOffice: tenant.data.taxOffice,
|
||
address1: tenant.data.address1,
|
||
address2: tenant.data.address2,
|
||
district: tenant.data.district,
|
||
country: tenant.data.country,
|
||
city: tenant.data.city,
|
||
postalCode: tenant.data.postalCode,
|
||
phoneNumber: tenant.data.phoneNumber,
|
||
mobileNumber: tenant.data.mobileNumber,
|
||
faxNumber: tenant.data.faxNumber,
|
||
email: tenant.data.email,
|
||
website: tenant.data.website,
|
||
menuGroup: tenant.data.menuGroup,
|
||
}))
|
||
} catch (error) {
|
||
console.error('Kurum bilgisi alınırken hata:', error)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="flex flex-col lg:flex-row gap-6 mb-6">
|
||
<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">
|
||
<FaUser className="w-5 h-5 text-green-600 mr-2" />{' '}
|
||
{translate('::Public.payment.customerInfo')}
|
||
</h2>
|
||
</div>
|
||
|
||
<div className="space-y-4">
|
||
<div className="grid grid-cols-1 gap-4">
|
||
<button
|
||
onClick={() => setIsExisting(true)}
|
||
className={`p-4 border-2 rounded-xl transition-all text-left select-none ${
|
||
isExisting === true
|
||
? 'border-blue-500 bg-blue-50 shadow-md scale-[1.02]'
|
||
: 'border-gray-200 hover:border-blue-300'
|
||
}`}
|
||
>
|
||
<div className="font-semibold text-gray-900 mb-2">
|
||
{translate('::Public.products.tenantForm.existing.title')}
|
||
</div>
|
||
<div className="text-sm text-gray-600">
|
||
{translate('::Public.products.tenantForm.existing.desc')}
|
||
</div>
|
||
</button>
|
||
|
||
<button
|
||
onClick={() => setIsExisting(false)}
|
||
className={`p-4 border-2 rounded-xl transition-all text-left select-none ${
|
||
isExisting === false
|
||
? 'border-blue-500 bg-blue-50 shadow-md scale-[1.02]'
|
||
: 'border-gray-200 hover:border-blue-300'
|
||
}`}
|
||
>
|
||
<div className="font-semibold text-gray-900 mb-2">
|
||
{translate('::Public.products.tenantForm.new.title')}
|
||
</div>
|
||
<div className="text-sm text-gray-600">
|
||
{translate('::Public.products.tenantForm.new.desc')}
|
||
</div>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="w-full lg:w-2/3 bg-white rounded-xl shadow-lg border border-gray-200 p-6">
|
||
{isExisting !== null && (
|
||
<form onSubmit={handleSubmit} className="space-y-6">
|
||
{isExisting ? (
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
{translate('::Public.payment.customer.code')}
|
||
</label>
|
||
<div className="relative flex flex-col sm:flex-row sm:items-stretch">
|
||
<div className="relative w-full">
|
||
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
autoFocus
|
||
placeholder="Enter your organization code"
|
||
value={formData.name || ''}
|
||
onChange={(e) => handleInputChange('name', e.target.value)}
|
||
onKeyDown={async (e) => {
|
||
if (e.key === 'Enter') {
|
||
e.preventDefault()
|
||
await getTenantInfo()
|
||
}
|
||
}}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg sm:rounded-l-lg sm:rounded-r-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||
/>
|
||
</div>
|
||
<button
|
||
type="button"
|
||
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-[180px]"
|
||
>
|
||
<FaSearch className="w-4 h-4" />
|
||
{translate('::Public.products.tenantForm.searchOrg')}
|
||
</button>
|
||
</div>
|
||
|
||
{formData.organizationName && (
|
||
<div className="grid grid-cols-1 gap-y-3 text-sm text-gray-700 p-3">
|
||
<div className="flex items-center gap-2">
|
||
<FaUser className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::LoginPanel.Profil')}
|
||
</span>
|
||
<span>{formData.founder}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaBuilding className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.payment.customer.company')}
|
||
</span>
|
||
<span>{formData.organizationName}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaEnvelope className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Abp.Account.EmailAddress')}:
|
||
</span>
|
||
<span>{formData.email}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaPhone className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::blog.categories.mobile')}:
|
||
</span>
|
||
<span>{formData.mobileNumber}</span>
|
||
</div>
|
||
|
||
<div className="flex items-start gap-2">
|
||
<FaMapPin className="w-4 h-4 text-gray-500 mt-0.5" />
|
||
<div>
|
||
<span className="font-medium">
|
||
{translate('::App.Address')}:
|
||
</span>
|
||
<div>{formData.address1}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaGlobe className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.payment.customer.country')}:
|
||
</span>
|
||
<span>{formData.country}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaGlobe className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.common.city')}:
|
||
</span>
|
||
<span>{formData.city}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaMap className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.payment.customer.district')}:
|
||
</span>
|
||
<span>{formData.district}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaMapPin className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.payment.customer.postalCode')}:
|
||
</span>
|
||
<span>{formData.postalCode}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaMoneyBillWave className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.contact.taxOffice')}:
|
||
</span>
|
||
<span>{formData.taxOffice}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<FaDollarSign className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.contact.taxNumber')}:
|
||
</span>
|
||
<span>{formData.vknTckn}</span>
|
||
</div>
|
||
|
||
{formData.reference && (
|
||
<div className="flex items-center gap-2">
|
||
<FaUserPlus className="w-4 h-4 text-gray-500" />
|
||
<span className="font-medium">
|
||
{translate('::Public.payment.customer.reference')}:
|
||
</span>
|
||
<span>{formData.reference}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
) : (
|
||
<div className="space-y-4">
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
{translate('::Public.products.tenantForm.orgName')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
autoFocus
|
||
placeholder="Enter your organization name"
|
||
value={formData.organizationName || ''}
|
||
onChange={(e) => handleInputChange('organizationName', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::LoginPanel.Profil')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaUser className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
placeholder="Enter founder's name"
|
||
value={formData.founder || ''}
|
||
onChange={(e) => handleInputChange('founder', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Abp.Identity.User.UserInformation.PhoneNumber')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaPhone className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="tel"
|
||
required
|
||
placeholder="+90 (___) ___-____"
|
||
value={formData.phoneNumber || ''}
|
||
onChange={(e) => handleInputChange('phoneNumber', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Abp.Account.EmailAddress')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaEnvelope className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="email"
|
||
required
|
||
placeholder="sample@email.com"
|
||
value={formData.email || ''}
|
||
onChange={(e) => handleInputChange('email', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::App.Address')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaMapPin className="absolute left-3 top-3 text-gray-400 w-5 h-5" />
|
||
<textarea
|
||
required
|
||
placeholder="Enter your address"
|
||
value={formData.address1 || ''}
|
||
onChange={(e) => handleInputChange('address1', e.target.value)}
|
||
rows={3}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.payment.customer.country')}
|
||
</label>
|
||
<div className="relative">
|
||
<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"
|
||
value={formData.country || ''}
|
||
onChange={(e) => handleInputChange('country', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.common.city')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
placeholder="İstanbul"
|
||
value={formData.city || ''}
|
||
onChange={(e) => handleInputChange('city', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.payment.customer.district')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
placeholder="Çekmeköy"
|
||
value={formData.district || ''}
|
||
onChange={(e) => handleInputChange('district', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.payment.customer.postalCode')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
placeholder="34782"
|
||
value={formData.postalCode || ''}
|
||
onChange={(e) => handleInputChange('postalCode', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.contact.taxOffice')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
placeholder="Kozyatağı"
|
||
value={formData.taxOffice}
|
||
onChange={(e) => handleInputChange('taxOffice', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.contact.taxNumber')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaDollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
required
|
||
placeholder="1234567890"
|
||
value={formData.vknTckn}
|
||
onChange={(e) => handleInputChange('vknTckn', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="text-sm font-medium text-gray-700">
|
||
{translate('::Public.payment.customer.reference')}
|
||
</label>
|
||
<div className="relative">
|
||
<FaUserPlus className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
|
||
<input
|
||
type="text"
|
||
placeholder={translate('::Public.payment.customer.reference')}
|
||
value={formData.reference || ''}
|
||
onChange={(e) => handleInputChange('reference', e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
<div className="flex justify-between items-center mt-6">
|
||
<button
|
||
type="button"
|
||
onClick={() => navigate(ROUTES_ENUM.public.products)}
|
||
className="flex items-center px-6 py-3 border border-gray-300 text-gray-700 rounded-lg"
|
||
>
|
||
<FaArrowLeft className="w-4 h-4 mr-2" />
|
||
{translate('::Public.payment.buttons.back')}
|
||
</button>
|
||
<button
|
||
type="submit"
|
||
className="flex items-center justify-center px-6 py-3 bg-green-600 text-white rounded-lg"
|
||
>
|
||
<FaArrowRight className="w-5 h-5 mr-2" />
|
||
{translate('::Abp.Account.ResetPassword.Continue')}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|