Enum ve static veriler düzenlendi.

This commit is contained in:
Sedat ÖZTÜRK 2025-09-17 12:46:58 +03:00
parent a86d0f9fd1
commit ca28fe8b5c
116 changed files with 4170 additions and 4649 deletions

View file

@ -82,7 +82,7 @@ define(['./workbox-a959eb95'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812" "revision": "3ca0b8505b4bec776b69afdba2768812"
}, { }, {
"url": "/index.html", "url": "/index.html",
"revision": "0.bkv2hic80pg" "revision": "0.h99odp2o5hg"
}], {}); }], {});
workbox.cleanupOutdatedCaches(); workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), { workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), {

View file

@ -368,7 +368,7 @@ const EntityManager: React.FC = () => {
</p> </p>
{!searchTerm && filterActive === 'all' && ( {!searchTerm && filterActive === 'all' && (
<Link <Link
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew} to={ROUTES_ENUM.protected.saas.developerKit.entitiesNew}
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" 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"
> >
<FaPlus className="w-4 h-4" /> <FaPlus className="w-4 h-4" />

View file

@ -1,54 +1,51 @@
import { BankAccountTypeEnum } from "../types/fi"; import { BankAccountTypeEnum } from '../types/fi'
import { BusinessParty, BusinessPartyStatusEnum, PartyType, PaymentTerms } from "../types/common"; import { BusinessParty, BusinessPartyStatusEnum, PartyType, PaymentTerms } from '../types/common'
import { import { CustomerSegmentEnum, CustomerTypeEnum } from '../types/crm'
CustomerSegmentEnum, import { SupplierTypeEnum, SupplierCardTypeEnum } from '../types/mm'
CustomerTypeEnum,
} from "../types/crm";
import { SupplierTypeEnum, SupplierCardTypeEnum } from "../types/mm";
export const mockBusinessParties: BusinessParty[] = [ export const mockBusinessParties: BusinessParty[] = [
{ {
id: "1", id: '1',
code: "SUP001", code: 'SUP001',
supplierType: SupplierTypeEnum.Material, supplierType: SupplierTypeEnum.Manufacturer,
name: "ABC Malzeme Ltd.", name: 'ABC Malzeme Ltd.',
primaryContact: { primaryContact: {
id: "2", id: '2',
firstName: "Fatma", firstName: 'Fatma',
lastName: "Demir", lastName: 'Demir',
fullName: "Fatma Demir", fullName: 'Fatma Demir',
title: "Genel Müdür", title: 'Genel Müdür',
department: "Yönetim", department: 'Yönetim',
email: "fatma.demir@uretim.com", email: 'fatma.demir@uretim.com',
phone: "+90 312 555 0202", phone: '+90 312 555 0202',
mobile: "+90 532 555 0202", mobile: '+90 532 555 0202',
isPrimary: true, isPrimary: true,
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}, },
email: "aliveli@gmail.com", email: 'aliveli@gmail.com',
phone: "+90 212 555 1234", phone: '+90 212 555 1234',
address: { address: {
street: "İstiklal Cad. No:10", street: 'İstiklal Cad. No:10',
city: "İstanbul", city: 'İstanbul',
state: "İstanbul", state: 'İstanbul',
postalCode: "34430", postalCode: '34430',
country: "Türkiye", country: 'Türkiye',
}, },
taxNumber: "1234567890", taxNumber: '1234567890',
paymentTerms: PaymentTerms.Net30, paymentTerms: PaymentTerms.Net30,
currency: "TRY", currency: 'TRY',
cardNumber: "SC-2024-001", cardNumber: 'SC-2024-001',
cardType: SupplierCardTypeEnum.Standard, cardType: SupplierCardTypeEnum.Standard,
validFrom: new Date("2024-01-01"), validFrom: new Date('2024-01-01'),
validTo: new Date("2024-12-31"), validTo: new Date('2024-12-31'),
creditLimit: 500000, creditLimit: 500000,
isActive: true, isActive: true,
currentBalance: 120000, currentBalance: 120000,
discountRate: 5, discountRate: 5,
specialConditions: ["Toplu sipariş indirimi", "Öncelikli teslimat"], specialConditions: ['Toplu sipariş indirimi', 'Öncelikli teslimat'],
lastOrderDate: new Date("2024-08-15"), lastOrderDate: new Date('2024-08-15'),
performanceMetrics: { performanceMetrics: {
deliveryPerformance: 95, deliveryPerformance: 95,
qualityRating: 90, qualityRating: 90,
@ -56,21 +53,21 @@ export const mockBusinessParties: BusinessParty[] = [
responsiveness: 67, responsiveness: 67,
complianceRating: 88, complianceRating: 88,
overallScore: 100, overallScore: 100,
lastEvaluationDate: new Date("2024-08-01"), lastEvaluationDate: new Date('2024-08-01'),
}, },
certifications: ["ISO 9001", "ISO 14001"], certifications: ['ISO 9001', 'ISO 14001'],
bankAccounts: [ bankAccounts: [
{ {
id: "BA001", id: 'BA001',
bankName: "Garanti BBVA", bankName: 'Garanti BBVA',
accountNumber: "1234567890", accountNumber: '1234567890',
iban: "TR330006100519786457841326", iban: 'TR330006100519786457841326',
swiftCode: "TGBATRIS", swiftCode: 'TGBATRIS',
isDefault: true, isDefault: true,
accountCode: "", accountCode: '',
branchName: "", branchName: '',
accountType: BankAccountTypeEnum.Current, accountType: BankAccountTypeEnum.Current,
currency: "", currency: '',
balance: 0, balance: 0,
overdraftLimit: 0, overdraftLimit: 0,
dailyTransferLimit: 0, dailyTransferLimit: 0,
@ -81,14 +78,14 @@ export const mockBusinessParties: BusinessParty[] = [
], ],
contacts: [ contacts: [
{ {
id: "C001", id: 'C001',
firstName: "Ali", firstName: 'Ali',
lastName: "Veli", lastName: 'Veli',
fullName: "Ali Veli", fullName: 'Ali Veli',
title: "Satınalma Müdürü", title: 'Satınalma Müdürü',
email: "aliveli@gmail.com", email: 'aliveli@gmail.com',
phone: "+90 212 555 1234", phone: '+90 212 555 1234',
department: "Satınalma", department: 'Satınalma',
isPrimary: true, isPrimary: true,
isActive: false, isActive: false,
creationTime: new Date(), creationTime: new Date(),
@ -100,47 +97,47 @@ export const mockBusinessParties: BusinessParty[] = [
partyType: PartyType.Supplier, partyType: PartyType.Supplier,
}, },
{ {
id: "2", id: '2',
code: "SUP002", code: 'SUP002',
supplierType: SupplierTypeEnum.Service, supplierType: SupplierTypeEnum.ServiceProvider,
name: "XYZ Teknoloji A.Ş.", name: 'XYZ Teknoloji A.Ş.',
primaryContact: { primaryContact: {
id: "2", id: '2',
firstName: "Fatma", firstName: 'Fatma',
lastName: "Demir", lastName: 'Demir',
fullName: "Fatma Demir", fullName: 'Fatma Demir',
title: "Genel Müdür", title: 'Genel Müdür',
department: "Yönetim", department: 'Yönetim',
email: "fatma.demir@uretim.com", email: 'fatma.demir@uretim.com',
phone: "+90 312 555 0202", phone: '+90 312 555 0202',
mobile: "+90 532 555 0202", mobile: '+90 532 555 0202',
isPrimary: true, isPrimary: true,
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}, },
email: "aysedemir@gmail.com", email: 'aysedemir@gmail.com',
phone: "+90 216 555 5678", phone: '+90 216 555 5678',
address: { address: {
street: "Barbaros Bulv. No:20", street: 'Barbaros Bulv. No:20',
city: "İstanbul", city: 'İstanbul',
state: "İstanbul", state: 'İstanbul',
postalCode: "34746", postalCode: '34746',
country: "Türkiye", country: 'Türkiye',
}, },
taxNumber: "0987654321", taxNumber: '0987654321',
paymentTerms: PaymentTerms.Net15, paymentTerms: PaymentTerms.Net15,
currency: "TRY", currency: 'TRY',
cardNumber: "SC-2024-002", cardNumber: 'SC-2024-002',
cardType: SupplierCardTypeEnum.Premium, cardType: SupplierCardTypeEnum.Premium,
validFrom: new Date("2024-02-01"), validFrom: new Date('2024-02-01'),
validTo: new Date("2024-12-31"), validTo: new Date('2024-12-31'),
creditLimit: 250000, creditLimit: 250000,
isActive: true, isActive: true,
currentBalance: 75000, currentBalance: 75000,
discountRate: 3, discountRate: 3,
specialConditions: ["Hızlı teslimat", "Kalite garantisi"], specialConditions: ['Hızlı teslimat', 'Kalite garantisi'],
lastOrderDate: new Date("2024-08-20"), lastOrderDate: new Date('2024-08-20'),
performanceMetrics: { performanceMetrics: {
deliveryPerformance: 88, deliveryPerformance: 88,
qualityRating: 90, qualityRating: 90,
@ -148,21 +145,21 @@ export const mockBusinessParties: BusinessParty[] = [
responsiveness: 87, responsiveness: 87,
complianceRating: 91, complianceRating: 91,
overallScore: 88, overallScore: 88,
lastEvaluationDate: new Date("2024-08-01"), lastEvaluationDate: new Date('2024-08-01'),
}, },
certifications: ["ISO 9001"], certifications: ['ISO 9001'],
bankAccounts: [ bankAccounts: [
{ {
id: "BA002", id: 'BA002',
bankName: "İş Bankası", bankName: 'İş Bankası',
accountNumber: "0987654321", accountNumber: '0987654321',
iban: "TR440006200519786457841327", iban: 'TR440006200519786457841327',
swiftCode: "ISBKTRIS", swiftCode: 'ISBKTRIS',
isDefault: true, isDefault: true,
accountCode: "", accountCode: '',
branchName: "", branchName: '',
accountType: BankAccountTypeEnum.Current, accountType: BankAccountTypeEnum.Current,
currency: "", currency: '',
balance: 0, balance: 0,
overdraftLimit: 0, overdraftLimit: 0,
dailyTransferLimit: 0, dailyTransferLimit: 0,
@ -173,14 +170,14 @@ export const mockBusinessParties: BusinessParty[] = [
], ],
contacts: [ contacts: [
{ {
id: "C002", id: 'C002',
firstName: "Ayşe", firstName: 'Ayşe',
lastName: "Demir", lastName: 'Demir',
fullName: "Ayşe Demir", fullName: 'Ayşe Demir',
title: "Satış Müdürü", title: 'Satış Müdürü',
email: "aysedemir@gmail.com", email: 'aysedemir@gmail.com',
phone: "+90 216 555 5678", phone: '+90 216 555 5678',
department: "Satış", department: 'Satış',
isPrimary: true, isPrimary: true,
isActive: false, isActive: false,
creationTime: new Date(), creationTime: new Date(),
@ -192,47 +189,47 @@ export const mockBusinessParties: BusinessParty[] = [
partyType: PartyType.Supplier, partyType: PartyType.Supplier,
}, },
{ {
id: "3", id: '3',
code: "SUP003", code: 'SUP003',
supplierType: SupplierTypeEnum.Both, supplierType: SupplierTypeEnum.Manufacturer,
name: "LMN Endüstri A.Ş.", name: 'LMN Endüstri A.Ş.',
primaryContact: { primaryContact: {
id: "2", id: '2',
firstName: "Fatma", firstName: 'Fatma',
lastName: "Demir", lastName: 'Demir',
fullName: "Fatma Demir", fullName: 'Fatma Demir',
title: "Genel Müdür", title: 'Genel Müdür',
department: "Yönetim", department: 'Yönetim',
email: "fatma.demir@uretim.com", email: 'fatma.demir@uretim.com',
phone: "+90 312 555 0202", phone: '+90 312 555 0202',
mobile: "+90 532 555 0202", mobile: '+90 532 555 0202',
isPrimary: true, isPrimary: true,
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}, },
email: "mehmetyilmaz@gmail.com", email: 'mehmetyilmaz@gmail.com',
phone: "+90 232 555 7890", phone: '+90 232 555 7890',
address: { address: {
street: "Atatürk Cad. No:5", street: 'Atatürk Cad. No:5',
city: "İzmir", city: 'İzmir',
state: "İzmir", state: 'İzmir',
postalCode: "35210", postalCode: '35210',
country: "Türkiye", country: 'Türkiye',
}, },
taxNumber: "1122334455", taxNumber: '1122334455',
paymentTerms: PaymentTerms.Net45, paymentTerms: PaymentTerms.Net45,
currency: "TRY", currency: 'TRY',
cardNumber: "SC-2024-003", cardNumber: 'SC-2024-003',
cardType: SupplierCardTypeEnum.Preferred, cardType: SupplierCardTypeEnum.Preferred,
validFrom: new Date("2024-03-01"), validFrom: new Date('2024-03-01'),
validTo: new Date("2024-12-31"), validTo: new Date('2024-12-31'),
creditLimit: 150000, creditLimit: 150000,
isActive: true, isActive: true,
currentBalance: 45000, currentBalance: 45000,
discountRate: 2, discountRate: 2,
specialConditions: ["Toplu sipariş indirimi"], specialConditions: ['Toplu sipariş indirimi'],
lastOrderDate: new Date("2024-08-18"), lastOrderDate: new Date('2024-08-18'),
performanceMetrics: { performanceMetrics: {
deliveryPerformance: 82, deliveryPerformance: 82,
qualityRating: 85, qualityRating: 85,
@ -240,21 +237,21 @@ export const mockBusinessParties: BusinessParty[] = [
responsiveness: 80, responsiveness: 80,
complianceRating: 88, complianceRating: 88,
overallScore: 85, overallScore: 85,
lastEvaluationDate: new Date("2024-07-15"), lastEvaluationDate: new Date('2024-07-15'),
}, },
certifications: ["ISO 9001", "OHSAS 18001"], certifications: ['ISO 9001', 'OHSAS 18001'],
bankAccounts: [ bankAccounts: [
{ {
id: "BA003", id: 'BA003',
bankName: "Yapı Kredi", bankName: 'Yapı Kredi',
accountNumber: "1122334455", accountNumber: '1122334455',
iban: "TR550006300519786457841328", iban: 'TR550006300519786457841328',
swiftCode: "YAPITRIS", swiftCode: 'YAPITRIS',
isDefault: true, isDefault: true,
accountCode: "", accountCode: '',
branchName: "", branchName: '',
accountType: BankAccountTypeEnum.Current, accountType: BankAccountTypeEnum.Current,
currency: "", currency: '',
balance: 0, balance: 0,
overdraftLimit: 0, overdraftLimit: 0,
dailyTransferLimit: 0, dailyTransferLimit: 0,
@ -265,14 +262,14 @@ export const mockBusinessParties: BusinessParty[] = [
], ],
contacts: [ contacts: [
{ {
id: "C003", id: 'C003',
firstName: "Mehmet", firstName: 'Mehmet',
lastName: "Yılmaz", lastName: 'Yılmaz',
fullName: "Mehmet Yılmaz", fullName: 'Mehmet Yılmaz',
title: "Genel Müdür", title: 'Genel Müdür',
email: "mehmetyilmaz@gmail.com", email: 'mehmetyilmaz@gmail.com',
phone: "+90 232 555 7890", phone: '+90 232 555 7890',
department: "Yönetim", department: 'Yönetim',
isPrimary: true, isPrimary: true,
isActive: false, isActive: false,
creationTime: new Date(), creationTime: new Date(),
@ -284,47 +281,47 @@ export const mockBusinessParties: BusinessParty[] = [
partyType: PartyType.Supplier, partyType: PartyType.Supplier,
}, },
{ {
id: "4", id: '4',
code: "SUP004", code: 'SUP004',
supplierType: SupplierTypeEnum.Material, supplierType: SupplierTypeEnum.Distributor,
name: "OPQ Ticaret Ltd.", name: 'OPQ Ticaret Ltd.',
primaryContact: { primaryContact: {
id: "2", id: '2',
firstName: "Fatma", firstName: 'Fatma',
lastName: "Demir", lastName: 'Demir',
fullName: "Fatma Demir", fullName: 'Fatma Demir',
title: "Genel Müdür", title: 'Genel Müdür',
department: "Yönetim", department: 'Yönetim',
email: "fatma.demir@uretim.com", email: 'fatma.demir@uretim.com',
phone: "+90 312 555 0202", phone: '+90 312 555 0202',
mobile: "+90 532 555 0202", mobile: '+90 532 555 0202',
isPrimary: true, isPrimary: true,
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}, },
email: "fatmacelik@gmail.com", email: 'fatmacelik@gmail.com',
phone: "+90 312 555 3456", phone: '+90 312 555 3456',
address: { address: {
street: "Kızılay Meydanı No:15", street: 'Kızılay Meydanı No:15',
city: "Ankara", city: 'Ankara',
state: "Ankara", state: 'Ankara',
postalCode: "06690", postalCode: '06690',
country: "Türkiye", country: 'Türkiye',
}, },
taxNumber: "6677889900", taxNumber: '6677889900',
paymentTerms: PaymentTerms.Net30, paymentTerms: PaymentTerms.Net30,
currency: "TRY", currency: 'TRY',
cardNumber: "SC-2024-004", cardNumber: 'SC-2024-004',
cardType: SupplierCardTypeEnum.Standard, cardType: SupplierCardTypeEnum.Standard,
validFrom: new Date("2024-04-01"), validFrom: new Date('2024-04-01'),
validTo: new Date("2024-12-31"), validTo: new Date('2024-12-31'),
creditLimit: 100000, creditLimit: 100000,
isActive: false, isActive: false,
currentBalance: 30000, currentBalance: 30000,
discountRate: 4, discountRate: 4,
specialConditions: ["Öncelikli sipariş", "Hızlı teslimat"], specialConditions: ['Öncelikli sipariş', 'Hızlı teslimat'],
lastOrderDate: new Date("2024-06-30"), lastOrderDate: new Date('2024-06-30'),
performanceMetrics: { performanceMetrics: {
deliveryPerformance: 75, deliveryPerformance: 75,
qualityRating: 78, qualityRating: 78,
@ -332,21 +329,21 @@ export const mockBusinessParties: BusinessParty[] = [
responsiveness: 76, responsiveness: 76,
complianceRating: 80, complianceRating: 80,
overallScore: 78, overallScore: 78,
lastEvaluationDate: new Date("2024-07-01"), lastEvaluationDate: new Date('2024-07-01'),
}, },
certifications: ["ISO 9001"], certifications: ['ISO 9001'],
bankAccounts: [ bankAccounts: [
{ {
id: "BA004", id: 'BA004',
bankName: "Halkbank", bankName: 'Halkbank',
accountNumber: "6677889900", accountNumber: '6677889900',
iban: "TR660006400519786457841329", iban: 'TR660006400519786457841329',
swiftCode: "HALKTRIS", swiftCode: 'HALKTRIS',
isDefault: true, isDefault: true,
accountCode: "", accountCode: '',
branchName: "", branchName: '',
accountType: BankAccountTypeEnum.Current, accountType: BankAccountTypeEnum.Current,
currency: "", currency: '',
balance: 0, balance: 0,
overdraftLimit: 0, overdraftLimit: 0,
dailyTransferLimit: 0, dailyTransferLimit: 0,
@ -357,14 +354,14 @@ export const mockBusinessParties: BusinessParty[] = [
], ],
contacts: [ contacts: [
{ {
id: "C004", id: 'C004',
firstName: "Fatma", firstName: 'Fatma',
lastName: "Çelik", lastName: 'Çelik',
fullName: "Fatma Çelik", fullName: 'Fatma Çelik',
title: "Finans Müdürü", title: 'Finans Müdürü',
email: "fatmacelik@gmail.com", email: 'fatmacelik@gmail.com',
phone: "+90 312 555 3456", phone: '+90 312 555 3456',
department: "Finans", department: 'Finans',
isPrimary: true, isPrimary: true,
isActive: false, isActive: false,
creationTime: new Date(), creationTime: new Date(),
@ -376,22 +373,22 @@ export const mockBusinessParties: BusinessParty[] = [
partyType: PartyType.Supplier, partyType: PartyType.Supplier,
}, },
{ {
id: "5", id: '5',
code: "CUST-002", code: 'CUST-002',
name: "Üretim Ltd.", name: 'Üretim Ltd.',
customerType: CustomerTypeEnum.Company, customerType: CustomerTypeEnum.Company,
industry: "İmalat", industry: 'İmalat',
website: "www.uretim.com", website: 'www.uretim.com',
primaryContact: { primaryContact: {
id: "2", id: '2',
firstName: "Fatma", firstName: 'Fatma',
lastName: "Demir", lastName: 'Demir',
fullName: "Fatma Demir", fullName: 'Fatma Demir',
title: "Genel Müdür", title: 'Genel Müdür',
department: "Yönetim", department: 'Yönetim',
email: "fatma.demir@uretim.com", email: 'fatma.demir@uretim.com',
phone: "+90 312 555 0202", phone: '+90 312 555 0202',
mobile: "+90 532 555 0202", mobile: '+90 532 555 0202',
isPrimary: true, isPrimary: true,
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
@ -399,50 +396,50 @@ export const mockBusinessParties: BusinessParty[] = [
}, },
contacts: [], contacts: [],
address: { address: {
street: "Sanayi Sitesi 5. Cadde No:25", street: 'Sanayi Sitesi 5. Cadde No:25',
city: "Ankara", city: 'Ankara',
state: "Ankara", state: 'Ankara',
postalCode: "06000", postalCode: '06000',
country: "Türkiye", country: 'Türkiye',
}, },
taxNumber: "0987654321", taxNumber: '0987654321',
registrationNumber: "REG-002", registrationNumber: 'REG-002',
creditLimit: 500000, creditLimit: 500000,
paymentTerms: PaymentTerms.Net60, paymentTerms: PaymentTerms.Net60,
currency: "TRY", currency: 'TRY',
status: BusinessPartyStatusEnum.Active, status: BusinessPartyStatusEnum.Active,
customerSegment: CustomerSegmentEnum.SMB, customerSegment: CustomerSegmentEnum.SMB,
assignedSalesRep: "REP-002", assignedSalesRep: 'REP-002',
teamId: "TEAM-001", teamId: 'TEAM-001',
totalRevenue: 850000, totalRevenue: 850000,
lastOrderDate: new Date("2024-01-10"), lastOrderDate: new Date('2024-01-10'),
averageOrderValue: 42500, averageOrderValue: 42500,
lifetimeValue: 1700000, lifetimeValue: 1700000,
opportunities: [], opportunities: [],
orders: [], orders: [],
activities: [], activities: [],
isActive: true, isActive: true,
creationTime: new Date("2023-09-20"), creationTime: new Date('2023-09-20'),
lastModificationTime: new Date("2024-01-18"), lastModificationTime: new Date('2024-01-18'),
partyType: PartyType.Customer, partyType: PartyType.Customer,
}, },
{ {
id: "6", id: '6',
code: "CUST-001", code: 'CUST-001',
name: "Teknoloji A.Ş.", name: 'Teknoloji A.Ş.',
customerType: CustomerTypeEnum.Company, customerType: CustomerTypeEnum.Company,
industry: "Teknoloji", industry: 'Teknoloji',
website: "www.teknoloji.com", website: 'www.teknoloji.com',
primaryContact: { primaryContact: {
id: "1", id: '1',
firstName: "Ali", firstName: 'Ali',
lastName: "Yılmaz", lastName: 'Yılmaz',
fullName: "Ali Yılmaz", fullName: 'Ali Yılmaz',
title: "Satınalma Müdürü", title: 'Satınalma Müdürü',
department: "Satınalma", department: 'Satınalma',
email: "ali.yilmaz@teknoloji.com", email: 'ali.yilmaz@teknoloji.com',
phone: "+90 212 555 0201", phone: '+90 212 555 0201',
mobile: "+90 532 555 0201", mobile: '+90 532 555 0201',
isPrimary: true, isPrimary: true,
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
@ -450,53 +447,53 @@ export const mockBusinessParties: BusinessParty[] = [
}, },
contacts: [], contacts: [],
address: { address: {
street: "Teknoloji Caddesi No:100", street: 'Teknoloji Caddesi No:100',
city: "İstanbul", city: 'İstanbul',
state: "İstanbul", state: 'İstanbul',
postalCode: "34000", postalCode: '34000',
country: "Türkiye", country: 'Türkiye',
}, },
taxNumber: "1234567890", taxNumber: '1234567890',
registrationNumber: "REG-001", registrationNumber: 'REG-001',
creditLimit: 1000000, creditLimit: 1000000,
paymentTerms: PaymentTerms.Net30, paymentTerms: PaymentTerms.Net30,
currency: "TRY", currency: 'TRY',
status: BusinessPartyStatusEnum.Active, status: BusinessPartyStatusEnum.Active,
customerSegment: CustomerSegmentEnum.Enterprise, customerSegment: CustomerSegmentEnum.Enterprise,
assignedSalesRep: "REP-001", assignedSalesRep: 'REP-001',
teamId: "TEAM-001", teamId: 'TEAM-001',
totalRevenue: 2500000, totalRevenue: 2500000,
lastOrderDate: new Date("2024-01-15"), lastOrderDate: new Date('2024-01-15'),
averageOrderValue: 125000, averageOrderValue: 125000,
lifetimeValue: 5000000, lifetimeValue: 5000000,
opportunities: [], opportunities: [],
orders: [], orders: [],
activities: [], activities: [],
isActive: true, isActive: true,
creationTime: new Date("2023-06-15"), creationTime: new Date('2023-06-15'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
partyType: PartyType.Customer, partyType: PartyType.Customer,
}, },
]; ]
export const mockBusinessPartyNew: BusinessParty = { export const mockBusinessPartyNew: BusinessParty = {
id: "", id: '',
code: "", code: '',
supplierType: SupplierTypeEnum.Both, supplierType: SupplierTypeEnum.ServiceProvider,
name: "", name: '',
email: "", email: '',
phone: "", phone: '',
address: { address: {
street: "", street: '',
city: "", city: '',
state: "", state: '',
postalCode: "", postalCode: '',
country: "", country: '',
}, },
taxNumber: "", taxNumber: '',
paymentTerms: PaymentTerms.Cash, paymentTerms: PaymentTerms.Cash,
currency: "TRY", currency: 'TRY',
cardNumber: "", cardNumber: '',
cardType: SupplierCardTypeEnum.Standard, cardType: SupplierCardTypeEnum.Standard,
validTo: new Date(), validTo: new Date(),
validFrom: new Date(), validFrom: new Date(),
@ -521,4 +518,4 @@ export const mockBusinessPartyNew: BusinessParty = {
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
partyType: PartyType.Supplier, partyType: PartyType.Supplier,
}; }

View file

@ -1,44 +1,44 @@
import { FiCheck, CheckStatusEnum, CheckTypeEnum } from "../types/fi"; import { FiCheck, CheckStatusEnum, TypeEnum } from '../types/fi'
import { mockCurrentAccounts } from "./mockCurrentAccounts"; import { mockCurrentAccounts } from './mockCurrentAccounts'
export const mockChecks: FiCheck[] = [ export const mockChecks: FiCheck[] = [
{ {
id: "1", id: '1',
checkNumber: "CHK-001", checkNumber: 'CHK-001',
bankName: "İş Bankası", bankName: 'İş Bankası',
branchName: "Levent Şubesi", branchName: 'Levent Şubesi',
accountNumber: "1234567890", accountNumber: '1234567890',
type: CheckTypeEnum.Received, type: TypeEnum.Received,
drawerName: "XYZ Müşteri A.Ş.", drawerName: 'XYZ Müşteri A.Ş.',
payeeName: "ABC Şirket", payeeName: 'ABC Şirket',
issueDate: new Date("2024-01-15"), issueDate: new Date('2024-01-15'),
dueDate: new Date("2024-02-15"), dueDate: new Date('2024-02-15'),
amount: 25000, amount: 25000,
currency: "TRY", currency: 'TRY',
status: CheckStatusEnum.InHand, status: CheckStatusEnum.InHand,
currentAccountId: "1", currentAccountId: '1',
currentAccount: mockCurrentAccounts.find((ca) => ca.id === "1"), currentAccount: mockCurrentAccounts.find((ca) => ca.id === '1'),
creationTime: new Date("2024-01-15"), creationTime: new Date('2024-01-15'),
lastModificationTime: new Date("2024-01-15"), lastModificationTime: new Date('2024-01-15'),
}, },
{ {
id: "2", id: '2',
checkNumber: "CHK-002", checkNumber: 'CHK-002',
bankName: "Garanti BBVA", bankName: 'Garanti BBVA',
branchName: "Şişli Şubesi", branchName: 'Şişli Şubesi',
accountNumber: "9876543210", accountNumber: '9876543210',
type: CheckTypeEnum.Issued, type: TypeEnum.Issued,
drawerName: "ABC Şirket", drawerName: 'ABC Şirket',
payeeName: "Tedarikçi Ltd.", payeeName: 'Tedarikçi Ltd.',
issueDate: new Date("2024-01-10"), issueDate: new Date('2024-01-10'),
dueDate: new Date("2024-02-10"), dueDate: new Date('2024-02-10'),
amount: 15000, amount: 15000,
currency: "TRY", currency: 'TRY',
status: CheckStatusEnum.Deposited, status: CheckStatusEnum.Deposited,
bankingDate: new Date("2024-01-20"), bankingDate: new Date('2024-01-20'),
currentAccountId: "2", currentAccountId: '2',
currentAccount: mockCurrentAccounts.find((ca) => ca.id === "2"), currentAccount: mockCurrentAccounts.find((ca) => ca.id === '2'),
creationTime: new Date("2024-01-10"), creationTime: new Date('2024-01-10'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
}, },
]; ]

View file

@ -1,80 +1,80 @@
import { PsProjectCostTracking } from "../types/ps"; import { ProjectCostTrackingStatus, PsProjectCostTracking } from '../types/ps'
export const mockProjectCostTracking: PsProjectCostTracking[] = [ export const mockProjectCostTracking: PsProjectCostTracking[] = [
{ {
id: "1", id: '1',
projectId: "1", projectId: '1',
projectName: "ERP Sistemi Geliştirme", projectName: 'ERP Sistemi Geliştirme',
projectCode: "PRJ-2024-001", projectCode: 'PRJ-2024-001',
plannedBudget: 500000, plannedBudget: 500000,
actualCost: 325000, actualCost: 325000,
remainingBudget: 175000, remainingBudget: 175000,
plannedStartDate: new Date("2024-01-15"), plannedStartDate: new Date('2024-01-15'),
plannedEndDate: new Date("2024-12-31"), plannedEndDate: new Date('2024-12-31'),
actualStartDate: new Date("2024-01-20"), actualStartDate: new Date('2024-01-20'),
actualEndDate: undefined, actualEndDate: undefined,
plannedDuration: 351, plannedDuration: 351,
actualDuration: 300, actualDuration: 300,
progress: 65, progress: 65,
status: "ON_TRACK", status: ProjectCostTrackingStatus.OnTrack,
currency: "TRY", currency: 'TRY',
lastUpdated: new Date("2024-11-25"), lastUpdated: new Date('2024-11-25'),
}, },
{ {
id: "2", id: '2',
projectId: "2", projectId: '2',
projectName: "Mobil Uygulama Geliştirme", projectName: 'Mobil Uygulama Geliştirme',
projectCode: "PRJ-2024-002", projectCode: 'PRJ-2024-002',
plannedBudget: 250000, plannedBudget: 250000,
actualCost: 200000, actualCost: 200000,
remainingBudget: 50000, remainingBudget: 50000,
plannedStartDate: new Date("2024-03-01"), plannedStartDate: new Date('2024-03-01'),
plannedEndDate: new Date("2024-08-31"), plannedEndDate: new Date('2024-08-31'),
actualStartDate: new Date("2024-03-15"), actualStartDate: new Date('2024-03-15'),
actualEndDate: undefined, actualEndDate: undefined,
plannedDuration: 184, plannedDuration: 184,
actualDuration: 200, actualDuration: 200,
progress: 80, progress: 80,
status: "AT_RISK", status: ProjectCostTrackingStatus.AtRisk,
currency: "TRY", currency: 'TRY',
lastUpdated: new Date("2024-11-20"), lastUpdated: new Date('2024-11-20'),
}, },
{ {
id: "3", id: '3',
projectId: "3", projectId: '3',
projectName: "Web Sitesi Yenileme", projectName: 'Web Sitesi Yenileme',
projectCode: "PRJ-2024-003", projectCode: 'PRJ-2024-003',
plannedBudget: 150000, plannedBudget: 150000,
actualCost: 180000, actualCost: 180000,
remainingBudget: -30000, remainingBudget: -30000,
plannedStartDate: new Date("2024-02-01"), plannedStartDate: new Date('2024-02-01'),
plannedEndDate: new Date("2024-06-30"), plannedEndDate: new Date('2024-06-30'),
actualStartDate: new Date("2024-02-10"), actualStartDate: new Date('2024-02-10'),
actualEndDate: new Date("2024-07-15"), actualEndDate: new Date('2024-07-15'),
plannedDuration: 150, plannedDuration: 150,
actualDuration: 156, actualDuration: 156,
progress: 100, progress: 100,
status: "COMPLETED", status: ProjectCostTrackingStatus.Completed,
currency: "TRY", currency: 'TRY',
lastUpdated: new Date("2024-07-15"), lastUpdated: new Date('2024-07-15'),
}, },
{ {
id: "4", id: '4',
projectId: "4", projectId: '4',
projectName: "Veri Analizi Platformu", projectName: 'Veri Analizi Platformu',
projectCode: "PRJ-2024-004", projectCode: 'PRJ-2024-004',
plannedBudget: 400000, plannedBudget: 400000,
actualCost: 120000, actualCost: 120000,
remainingBudget: 280000, remainingBudget: 280000,
plannedStartDate: new Date("2024-06-01"), plannedStartDate: new Date('2024-06-01'),
plannedEndDate: new Date("2024-12-31"), plannedEndDate: new Date('2024-12-31'),
actualStartDate: new Date("2024-06-15"), actualStartDate: new Date('2024-06-15'),
actualEndDate: undefined, actualEndDate: undefined,
plannedDuration: 214, plannedDuration: 214,
actualDuration: 163, actualDuration: 163,
progress: 30, progress: 30,
status: "DELAYED", status: ProjectCostTrackingStatus.Delayed,
currency: "TRY", currency: 'TRY',
lastUpdated: new Date("2024-11-22"), lastUpdated: new Date('2024-11-22'),
}, },
]; ]

View file

@ -1,180 +1,164 @@
import { PhaseStatusEnum, PsProjectPhase } from "../types/ps"; import { PhaseCategoryEnum, PhaseStatusEnum, PsProjectPhase } from '../types/ps'
import { mockMaintenanceTeams } from "./mockMaintenanceTeams"; import { mockMaintenanceTeams } from './mockMaintenanceTeams'
import { mockProjects } from "./mockProjects"; import { mockProjects } from './mockProjects'
export const mockProjectPhases: PsProjectPhase[] = [ export const mockProjectPhases: PsProjectPhase[] = [
{ {
id: "1", id: '1',
code: "PH-001", code: 'PH-001',
name: "Analiz ve Tasarım", name: 'Analiz ve Tasarım',
description: "Sistem analizi ve tasarım dokümantasyonu hazırlanması", description: 'Sistem analizi ve tasarım dokümantasyonu hazırlanması',
projectId: "1", projectId: '1',
project: mockProjects.find((p) => p.id === "1")!, project: mockProjects.find((p) => p.id === '1')!,
status: PhaseStatusEnum.Completed, status: PhaseStatusEnum.Completed,
startDate: new Date("2024-01-15"), startDate: new Date('2024-01-15'),
endDate: new Date("2024-02-28"), endDate: new Date('2024-02-28'),
actualStartDate: new Date("2024-01-15"), actualStartDate: new Date('2024-01-15'),
actualEndDate: new Date("2024-02-25"), actualEndDate: new Date('2024-02-25'),
budget: 150000, budget: 150000,
actualCost: 145000, actualCost: 145000,
progress: 100, progress: 100,
milestones: 4, milestones: 4,
completedMilestones: 4, completedMilestones: 4,
assignedTeams: [ assignedTeams: [
mockMaintenanceTeams.find((t) => t.id === "1")!.name, mockMaintenanceTeams.find((t) => t.id === '1')!.name,
mockMaintenanceTeams.find((t) => t.id === "2")!.name, mockMaintenanceTeams.find((t) => t.id === '2')!.name,
], ],
deliverables: [ deliverables: ['Sistem Analiz Raporu', 'Teknik Tasarım Dokümanı', 'UI/UX Tasarımları'],
"Sistem Analiz Raporu", risks: ['Gereksinim değişiklikleri'],
"Teknik Tasarım Dokümanı", category: PhaseCategoryEnum.Planning,
"UI/UX Tasarımları",
],
risks: ["Gereksinim değişiklikleri"],
category: "Planning",
sequence: 0, sequence: 0,
tasks: [], tasks: [],
isActive: false, isActive: false,
}, },
{ {
id: "2", id: '2',
code: "PH-002", code: 'PH-002',
name: "Geliştirme - Faz 1", name: 'Geliştirme - Faz 1',
description: "Backend altyapısı ve temel modüllerin geliştirilmesi", description: 'Backend altyapısı ve temel modüllerin geliştirilmesi',
projectId: "1", projectId: '1',
project: mockProjects.find((p) => p.id === "1")!, project: mockProjects.find((p) => p.id === '1')!,
status: PhaseStatusEnum.Cancelled, status: PhaseStatusEnum.Cancelled,
startDate: new Date("2024-03-01"), startDate: new Date('2024-03-01'),
endDate: new Date("2024-05-15"), endDate: new Date('2024-05-15'),
actualStartDate: new Date("2024-03-01"), actualStartDate: new Date('2024-03-01'),
actualEndDate: new Date("2024-05-10"), actualEndDate: new Date('2024-05-10'),
budget: 400000, budget: 400000,
actualCost: 280000, actualCost: 280000,
progress: 70, progress: 70,
milestones: 6, milestones: 6,
completedMilestones: 4, completedMilestones: 4,
assignedTeams: [ assignedTeams: [
mockMaintenanceTeams.find((t) => t.id === "1")!.name, mockMaintenanceTeams.find((t) => t.id === '1')!.name,
mockMaintenanceTeams.find((t) => t.id === "2")!.name, mockMaintenanceTeams.find((t) => t.id === '2')!.name,
], ],
deliverables: ["API Framework", "Veritabanı Şeması", "Güvenlik Modülü"], deliverables: ['API Framework', 'Veritabanı Şeması', 'Güvenlik Modülü'],
risks: ["Performans sorunları", "Üçüncü parti entegrasyon gecikmeleri"], risks: ['Performans sorunları', 'Üçüncü parti entegrasyon gecikmeleri'],
category: "Development", category: PhaseCategoryEnum.Development,
sequence: 0, sequence: 0,
tasks: [], tasks: [],
isActive: false, isActive: false,
}, },
{ {
id: "3", id: '3',
code: "PH-003", code: 'PH-003',
name: "Geliştirme - Faz 2", name: 'Geliştirme - Faz 2',
description: "Frontend geliştirme ve kullanıcı arayüzleri", description: 'Frontend geliştirme ve kullanıcı arayüzleri',
projectId: "1", projectId: '1',
project: mockProjects.find((p) => p.id === "1")!, project: mockProjects.find((p) => p.id === '1')!,
status: PhaseStatusEnum.NotStarted, status: PhaseStatusEnum.NotStarted,
startDate: new Date("2024-04-15"), startDate: new Date('2024-04-15'),
endDate: new Date("2024-07-30"), endDate: new Date('2024-07-30'),
budget: 350000, budget: 350000,
actualCost: 0, actualCost: 0,
progress: 0, progress: 0,
milestones: 5, milestones: 5,
completedMilestones: 0, completedMilestones: 0,
assignedTeams: [ assignedTeams: [
mockMaintenanceTeams.find((t) => t.id === "1")!.name, mockMaintenanceTeams.find((t) => t.id === '1')!.name,
mockMaintenanceTeams.find((t) => t.id === "2")!.name, mockMaintenanceTeams.find((t) => t.id === '2')!.name,
], ],
deliverables: [ deliverables: ['React Bileşenleri', 'Responsive Tasarım', 'Mobil Uyumluluk'],
"React Bileşenleri", risks: ['Tarayıcı uyumluluk sorunları', 'Performans optimizasyonu'],
"Responsive Tasarım", category: PhaseCategoryEnum.Development,
"Mobil Uyumluluk",
],
risks: ["Tarayıcı uyumluluk sorunları", "Performans optimizasyonu"],
category: "Development",
sequence: 0, sequence: 0,
tasks: [], tasks: [],
isActive: false, isActive: false,
}, },
{ {
id: "4", id: '4',
code: "PH-004", code: 'PH-004',
name: "Test ve Kalite Güvence", name: 'Test ve Kalite Güvence',
description: "Kapsamlı test süreçleri ve kalite kontrolleri", description: 'Kapsamlı test süreçleri ve kalite kontrolleri',
projectId: "2", projectId: '2',
project: mockProjects.find((p) => p.id === "2")!, project: mockProjects.find((p) => p.id === '2')!,
status: PhaseStatusEnum.NotStarted, status: PhaseStatusEnum.NotStarted,
startDate: new Date("2024-07-01"), startDate: new Date('2024-07-01'),
endDate: new Date("2024-09-15"), endDate: new Date('2024-09-15'),
budget: 120000, budget: 120000,
actualCost: 0, actualCost: 0,
progress: 0, progress: 0,
milestones: 3, milestones: 3,
completedMilestones: 0, completedMilestones: 0,
assignedTeams: [ assignedTeams: [
mockMaintenanceTeams.find((t) => t.id === "3")!.name, mockMaintenanceTeams.find((t) => t.id === '3')!.name,
mockMaintenanceTeams.find((t) => t.id === "4")!.name, mockMaintenanceTeams.find((t) => t.id === '4')!.name,
], ],
deliverables: [ deliverables: ['Test Senaryoları', 'Otomatik Test Süitleri', 'Kalite Raporu'],
"Test Senaryoları", risks: ['Kritik hataların geç tespit edilmesi'],
"Otomatik Test Süitleri", category: PhaseCategoryEnum.Testing,
"Kalite Raporu",
],
risks: ["Kritik hataların geç tespit edilmesi"],
category: "Testing",
sequence: 0, sequence: 0,
tasks: [], tasks: [],
isActive: false, isActive: false,
}, },
{ {
id: "5", id: '5',
code: "PH-005", code: 'PH-005',
name: "Deployment ve Go-Live", name: 'Deployment ve Go-Live',
description: "Üretime alma ve kullanıcı eğitimleri", description: 'Üretime alma ve kullanıcı eğitimleri',
projectId: "2", projectId: '2',
project: mockProjects.find((p) => p.id === "2")!, project: mockProjects.find((p) => p.id === '2')!,
status: PhaseStatusEnum.NotStarted, status: PhaseStatusEnum.NotStarted,
startDate: new Date("2024-09-15"), startDate: new Date('2024-09-15'),
endDate: new Date("2024-10-31"), endDate: new Date('2024-10-31'),
budget: 80000, budget: 80000,
actualCost: 0, actualCost: 0,
progress: 0, progress: 0,
milestones: 2, milestones: 2,
completedMilestones: 0, completedMilestones: 0,
assignedTeams: [ assignedTeams: [
mockMaintenanceTeams.find((t) => t.id === "2")!.name, mockMaintenanceTeams.find((t) => t.id === '2')!.name,
mockMaintenanceTeams.find((t) => t.id === "4")!.name, mockMaintenanceTeams.find((t) => t.id === '4')!.name,
], ],
deliverables: [ deliverables: ['Prodüksiyon Ortamı', 'Kullanıcı Eğitimleri', 'Dokümentasyon'],
"Prodüksiyon Ortamı", risks: ['Sistem kesintileri', 'Kullanıcı adaptasyon sorunları'],
"Kullanıcı Eğitimleri", category: PhaseCategoryEnum.Deployment,
"Dokümentasyon",
],
risks: ["Sistem kesintileri", "Kullanıcı adaptasyon sorunları"],
category: "Deployment",
sequence: 0, sequence: 0,
tasks: [], tasks: [],
isActive: false, isActive: false,
}, },
{ {
id: "6", id: '6',
code: "PH-006", code: 'PH-006',
name: "Mobil UI Tasarımı", name: 'Mobil UI Tasarımı',
description: "Mobil uygulama kullanıcı arayüzü tasarımı", description: 'Mobil uygulama kullanıcı arayüzü tasarımı',
projectId: "2", projectId: '2',
project: mockProjects.find((p) => p.id === "2")!, project: mockProjects.find((p) => p.id === '2')!,
status: PhaseStatusEnum.OnHold, status: PhaseStatusEnum.OnHold,
startDate: new Date("2024-03-01"), startDate: new Date('2024-03-01'),
endDate: new Date("2024-04-15"), endDate: new Date('2024-04-15'),
actualStartDate: new Date("2024-03-05"), actualStartDate: new Date('2024-03-05'),
budget: 75000, budget: 75000,
actualCost: 25000, actualCost: 25000,
progress: 35, progress: 35,
milestones: 3, milestones: 3,
completedMilestones: 1, completedMilestones: 1,
assignedTeams: [mockMaintenanceTeams.find((t) => t.id === "1")!.name], assignedTeams: [mockMaintenanceTeams.find((t) => t.id === '1')!.name],
deliverables: ["Wireframe'ler", "Mobil Tasarım Kılavuzu", "Prototype"], deliverables: ["Wireframe'ler", 'Mobil Tasarım Kılavuzu', 'Prototype'],
risks: ["Platformlar arası tutarlılık sorunları"], risks: ['Platformlar arası tutarlılık sorunları'],
category: "Design", category: PhaseCategoryEnum.Design,
sequence: 0, sequence: 0,
tasks: [], tasks: [],
isActive: false, isActive: false,
}, },
]; ]

View file

@ -1,40 +1,40 @@
import { NoteStatusEnum, NoteTypeEnum, PromissoryNote } from "../types/fi"; import { NoteStatusEnum, PromissoryNote, TypeEnum } from '../types/fi'
import { mockCurrentAccounts } from "./mockCurrentAccounts"; import { mockCurrentAccounts } from './mockCurrentAccounts'
export const mockPromissoryNotes: PromissoryNote[] = [ export const mockPromissoryNotes: PromissoryNote[] = [
{ {
id: "1", id: '1',
noteNumber: "NOT-001", noteNumber: 'NOT-001',
type: NoteTypeEnum.Received, type: TypeEnum.Received,
drawerName: "Müşteri A.Ş.", drawerName: 'Müşteri A.Ş.',
payeeName: "ABC Şirket", payeeName: 'ABC Şirket',
issueDate: new Date("2024-01-20"), issueDate: new Date('2024-01-20'),
dueDate: new Date("2024-03-20"), dueDate: new Date('2024-03-20'),
amount: 50000, amount: 50000,
currency: "TRY", currency: 'TRY',
status: NoteStatusEnum.InHand, status: NoteStatusEnum.InHand,
location: "Ana Kasa", location: 'Ana Kasa',
currentAccountId: "1", currentAccountId: '1',
currentAccount: mockCurrentAccounts.find((acc) => acc.id === "1"), currentAccount: mockCurrentAccounts.find((acc) => acc.id === '1'),
creationTime: new Date("2024-01-20"), creationTime: new Date('2024-01-20'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
}, },
{ {
id: "2", id: '2',
noteNumber: "NOT-002", noteNumber: 'NOT-002',
type: NoteTypeEnum.Issued, type: TypeEnum.Issued,
drawerName: "ABC Şirket", drawerName: 'ABC Şirket',
payeeName: "Kefil A.Ş.", payeeName: 'Kefil A.Ş.',
issueDate: new Date("2024-01-05"), issueDate: new Date('2024-01-05'),
dueDate: new Date("2024-03-05"), dueDate: new Date('2024-03-05'),
amount: 30000, amount: 30000,
currency: "TRY", currency: 'TRY',
status: NoteStatusEnum.Collected, status: NoteStatusEnum.Collected,
location: "Banka", location: 'Banka',
collectionDate: new Date("2024-01-25"), collectionDate: new Date('2024-01-25'),
currentAccountId: "2", currentAccountId: '2',
currentAccount: mockCurrentAccounts.find((acc) => acc.id === "2"), currentAccount: mockCurrentAccounts.find((acc) => acc.id === '2'),
creationTime: new Date("2024-01-05"), creationTime: new Date('2024-01-05'),
lastModificationTime: new Date("2024-01-25"), lastModificationTime: new Date('2024-01-25'),
}, },
]; ]

View file

@ -0,0 +1,28 @@
import { PmMachineType } from '../types/pm'
export const mockWorkCenterMachineTypes: PmMachineType[] = [
{
id: '1',
code: 'CNC',
name: 'CNC Makineleri',
isActive: true,
},
{
id: '2',
code: 'COMP',
name: 'Kompresörler',
isActive: true,
},
{
id: '3',
code: 'CONV',
name: 'Konveyörler',
isActive: true,
},
{
id: '4',
code: 'WELD',
name: 'Kaynak Makineleri',
isActive: true,
},
]

View file

@ -1,42 +1,39 @@
import { import { CriticalityLevelEnum, PmWorkCenter, WorkCenterStatusEnum } from '../types/pm'
CriticalityLevelEnum, import { mockWorkCenterMachineTypes } from './mockWorkCenterMachineTypes'
PmWorkCenter, import { mockWorkCenterTypes } from './mockWorkCenterTypes'
WorkCenterStatusEnum,
} from "../types/pm";
import { mockWorkCenterTypes } from "./mockWorkCenterTypes";
export const mockWorkCenters: PmWorkCenter[] = [ export const mockWorkCenters: PmWorkCenter[] = [
{ {
id: "1", id: '1',
code: "CNC-001", code: 'CNC-001',
name: "CNC Torna Tezgahı", name: 'CNC Torna Tezgahı',
description: "Yüksek hassasiyetli CNC torna tezgahı", description: 'Yüksek hassasiyetli CNC torna tezgahı',
workCenterId: "1", workCenterId: '1',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "1")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '1')!,
manufacturer: "HAAS Automation", manufacturer: 'HAAS Automation',
model: "ST-30", model: 'ST-30',
serialNumber: "SN123456789", serialNumber: 'SN123456789',
installationDate: new Date("2022-03-15"), installationDate: new Date('2022-03-15'),
warrantyExpiry: new Date("2025-03-15"), warrantyExpiry: new Date('2025-03-15'),
location: "Atölye A - Hat 1", location: 'Atölye A - Hat 1',
departmentId: "1", departmentId: '1',
status: WorkCenterStatusEnum.Operational, status: WorkCenterStatusEnum.Operational,
criticality: CriticalityLevelEnum.High, criticality: CriticalityLevelEnum.High,
specifications: [ specifications: [
{ {
id: "SPEC001", id: 'SPEC001',
workCenterId: "EQP001", workCenterId: 'EQP001',
specificationName: "Max Çap", specificationName: 'Max Çap',
specificationValue: "300", specificationValue: '300',
unit: "mm", unit: 'mm',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC002", id: 'SPEC002',
workCenterId: "EQP001", workCenterId: 'EQP001',
specificationName: "Motor Gücü", specificationName: 'Motor Gücü',
specificationValue: "15", specificationValue: '15',
unit: "kW", unit: 'kW',
isRequired: true, isRequired: true,
}, },
], ],
@ -44,44 +41,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2022-03-15"), creationTime: new Date('2022-03-15'),
lastModificationTime: new Date("2024-01-15"), lastModificationTime: new Date('2024-01-15'),
capacity: 8, capacity: 8,
costPerHour: 75, costPerHour: 75,
setupTime: 15, setupTime: 15,
machineType: "CNC", machineTypeId: '1',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
}, },
{ {
id: "2", id: '2',
code: "COMP-001", code: 'COMP-001',
name: "Hava Kompresörü", name: 'Hava Kompresörü',
description: "Endüstriyel hava kompresörü sistemi", description: 'Endüstriyel hava kompresörü sistemi',
workCenterId: "2", workCenterId: '2',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "2")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '2')!,
manufacturer: "Atlas Copco", manufacturer: 'Atlas Copco',
model: "GA55VSD+", model: 'GA55VSD+',
serialNumber: "AC987654321", serialNumber: 'AC987654321',
installationDate: new Date("2021-08-20"), installationDate: new Date('2021-08-20'),
warrantyExpiry: new Date("2024-08-20"), warrantyExpiry: new Date('2024-08-20'),
location: "Kompresör Odası", location: 'Kompresör Odası',
departmentId: "2", departmentId: '2',
status: WorkCenterStatusEnum.UnderMaintenance, status: WorkCenterStatusEnum.UnderMaintenance,
criticality: CriticalityLevelEnum.Critical, criticality: CriticalityLevelEnum.Critical,
specifications: [ specifications: [
{ {
id: "SPEC003", id: 'SPEC003',
workCenterId: "EQP002", workCenterId: 'EQP002',
specificationName: "Basınç", specificationName: 'Basınç',
specificationValue: "8.5", specificationValue: '8.5',
unit: "bar", unit: 'bar',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC004", id: 'SPEC004',
workCenterId: "EQP002", workCenterId: 'EQP002',
specificationName: "Kapasite", specificationName: 'Kapasite',
specificationValue: "55", specificationValue: '55',
unit: "kW", unit: 'kW',
isRequired: true, isRequired: true,
}, },
], ],
@ -89,43 +87,44 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2021-08-20"), creationTime: new Date('2021-08-20'),
lastModificationTime: new Date("2024-02-01"), lastModificationTime: new Date('2024-02-01'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '2',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '2')!,
capacity: 8, capacity: 8,
}, },
{ {
id: "3", id: '3',
code: "CONV-001", code: 'CONV-001',
name: "Konveyör Sistemi", name: 'Konveyör Sistemi',
description: "Ana hat konveyör sistemi", description: 'Ana hat konveyör sistemi',
workCenterId: "3", workCenterId: '3',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "3")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '3')!,
manufacturer: "Siemens", manufacturer: 'Siemens',
model: "SIMATIC S7-1500", model: 'SIMATIC S7-1500',
serialNumber: "SM112233445", serialNumber: 'SM112233445',
installationDate: new Date("2020-11-10"), installationDate: new Date('2020-11-10'),
location: "Ana Üretim Hattı", location: 'Ana Üretim Hattı',
departmentId: "3", departmentId: '3',
status: WorkCenterStatusEnum.OutOfOrder, status: WorkCenterStatusEnum.OutOfOrder,
criticality: CriticalityLevelEnum.Medium, criticality: CriticalityLevelEnum.Medium,
specifications: [ specifications: [
{ {
id: "SPEC005", id: 'SPEC005',
workCenterId: "EQP003", workCenterId: 'EQP003',
specificationName: "Hız", specificationName: 'Hız',
specificationValue: "2.5", specificationValue: '2.5',
unit: "m/s", unit: 'm/s',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC006", id: 'SPEC006',
workCenterId: "EQP003", workCenterId: 'EQP003',
specificationName: "Yük Kapasitesi", specificationName: 'Yük Kapasitesi',
specificationValue: "500", specificationValue: '500',
unit: "kg", unit: 'kg',
isRequired: true, isRequired: true,
}, },
], ],
@ -133,44 +132,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2020-11-10"), creationTime: new Date('2020-11-10'),
lastModificationTime: new Date("2024-02-05"), lastModificationTime: new Date('2024-02-05'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '3',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '3')!,
capacity: 8, capacity: 8,
}, },
{ {
id: "4", id: '4',
code: "KELD-001", code: 'KELD-001',
name: "Kaynak Makinesi", name: 'Kaynak Makinesi',
description: "Otomatik robot kaynak sistemi", description: 'Otomatik robot kaynak sistemi',
workCenterId: "4", workCenterId: '4',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
manufacturer: "KUKA", manufacturer: 'KUKA',
model: "KR 60-3", model: 'KR 60-3',
serialNumber: "KU556677889", serialNumber: 'KU556677889',
installationDate: new Date("2023-01-15"), installationDate: new Date('2023-01-15'),
warrantyExpiry: new Date("2026-01-15"), warrantyExpiry: new Date('2026-01-15'),
location: "Kaynak Atölyesi", location: 'Kaynak Atölyesi',
departmentId: "4", departmentId: '4',
status: WorkCenterStatusEnum.Operational, status: WorkCenterStatusEnum.Operational,
criticality: CriticalityLevelEnum.High, criticality: CriticalityLevelEnum.High,
specifications: [ specifications: [
{ {
id: "SPEC007", id: 'SPEC007',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Erişim Mesafesi", specificationName: 'Erişim Mesafesi',
specificationValue: "2033", specificationValue: '2033',
unit: "mm", unit: 'mm',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC008", id: 'SPEC008',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Taşıma Kapasitesi", specificationName: 'Taşıma Kapasitesi',
specificationValue: "60", specificationValue: '60',
unit: "kg", unit: 'kg',
isRequired: true, isRequired: true,
}, },
], ],
@ -178,44 +178,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2023-01-15"), creationTime: new Date('2023-01-15'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '3',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '3')!,
capacity: 8, capacity: 8,
}, },
{ {
id: "5", id: '5',
code: "WELL-001", code: 'WELL-001',
name: "Yıkama Makinesi", name: 'Yıkama Makinesi',
description: "Otomatik robot kaynak sistemi", description: 'Otomatik robot kaynak sistemi',
workCenterId: "4", workCenterId: '4',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
manufacturer: "KUKA", manufacturer: 'KUKA',
model: "KR 60-3", model: 'KR 60-3',
serialNumber: "KU556677889", serialNumber: 'KU556677889',
installationDate: new Date("2023-01-15"), installationDate: new Date('2023-01-15'),
warrantyExpiry: new Date("2026-01-15"), warrantyExpiry: new Date('2026-01-15'),
location: "Kaynak Atölyesi", location: 'Kaynak Atölyesi',
departmentId: "4", departmentId: '4',
status: WorkCenterStatusEnum.Operational, status: WorkCenterStatusEnum.Operational,
criticality: CriticalityLevelEnum.High, criticality: CriticalityLevelEnum.High,
specifications: [ specifications: [
{ {
id: "SPEC007", id: 'SPEC007',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Erişim Mesafesi", specificationName: 'Erişim Mesafesi',
specificationValue: "2033", specificationValue: '2033',
unit: "mm", unit: 'mm',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC008", id: 'SPEC008',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Taşıma Kapasitesi", specificationName: 'Taşıma Kapasitesi',
specificationValue: "60", specificationValue: '60',
unit: "kg", unit: 'kg',
isRequired: true, isRequired: true,
}, },
], ],
@ -223,44 +224,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2023-01-15"), creationTime: new Date('2023-01-15'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '4',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '4')!,
capacity: 8, capacity: 8,
}, },
{ {
id: "6", id: '6',
code: "KELD-001", code: 'KELD-001',
name: "Ram Makinesi", name: 'Ram Makinesi',
description: "Otomatik robot kaynak sistemi", description: 'Otomatik robot kaynak sistemi',
workCenterId: "4", workCenterId: '4',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
manufacturer: "KUKA", manufacturer: 'KUKA',
model: "KR 60-3", model: 'KR 60-3',
serialNumber: "KU556677889", serialNumber: 'KU556677889',
installationDate: new Date("2023-01-15"), installationDate: new Date('2023-01-15'),
warrantyExpiry: new Date("2026-01-15"), warrantyExpiry: new Date('2026-01-15'),
location: "Kaynak Atölyesi", location: 'Kaynak Atölyesi',
departmentId: "4", departmentId: '4',
status: WorkCenterStatusEnum.Operational, status: WorkCenterStatusEnum.Operational,
criticality: CriticalityLevelEnum.High, criticality: CriticalityLevelEnum.High,
specifications: [ specifications: [
{ {
id: "SPEC007", id: 'SPEC007',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Erişim Mesafesi", specificationName: 'Erişim Mesafesi',
specificationValue: "2033", specificationValue: '2033',
unit: "mm", unit: 'mm',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC008", id: 'SPEC008',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Taşıma Kapasitesi", specificationName: 'Taşıma Kapasitesi',
specificationValue: "60", specificationValue: '60',
unit: "kg", unit: 'kg',
isRequired: true, isRequired: true,
}, },
], ],
@ -268,44 +270,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2023-01-15"), creationTime: new Date('2023-01-15'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '4',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '4')!,
capacity: 8, capacity: 8,
}, },
{ {
id: "7", id: '7',
code: "WEID-001", code: 'WEID-001',
name: "Sarma Makinesi", name: 'Sarma Makinesi',
description: "Otomatik robot kaynak sistemi", description: 'Otomatik robot kaynak sistemi',
workCenterId: "4", workCenterId: '4',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
manufacturer: "KUKA", manufacturer: 'KUKA',
model: "KR 60-3", model: 'KR 60-3',
serialNumber: "KU556677889", serialNumber: 'KU556677889',
installationDate: new Date("2023-01-15"), installationDate: new Date('2023-01-15'),
warrantyExpiry: new Date("2026-01-15"), warrantyExpiry: new Date('2026-01-15'),
location: "Kaynak Atölyesi", location: 'Kaynak Atölyesi',
departmentId: "4", departmentId: '4',
status: WorkCenterStatusEnum.Operational, status: WorkCenterStatusEnum.Operational,
criticality: CriticalityLevelEnum.High, criticality: CriticalityLevelEnum.High,
specifications: [ specifications: [
{ {
id: "SPEC007", id: 'SPEC007',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Erişim Mesafesi", specificationName: 'Erişim Mesafesi',
specificationValue: "2033", specificationValue: '2033',
unit: "mm", unit: 'mm',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC008", id: 'SPEC008',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Taşıma Kapasitesi", specificationName: 'Taşıma Kapasitesi',
specificationValue: "60", specificationValue: '60',
unit: "kg", unit: 'kg',
isRequired: true, isRequired: true,
}, },
], ],
@ -313,44 +316,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2023-01-15"), creationTime: new Date('2023-01-15'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '1',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
capacity: 8, capacity: 8,
}, },
{ {
id: "8", id: '8',
code: "KEL-001", code: 'KEL-001',
name: "Robot Kaynak Makinesi", name: 'Robot Kaynak Makinesi',
description: "Otomatik robot kaynak sistemi", description: 'Otomatik robot kaynak sistemi',
workCenterId: "4", workCenterId: '4',
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!, workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
manufacturer: "KUKA", manufacturer: 'KUKA',
model: "KR 60-3", model: 'KR 60-3',
serialNumber: "KU556677889", serialNumber: 'KU556677889',
installationDate: new Date("2023-01-15"), installationDate: new Date('2023-01-15'),
warrantyExpiry: new Date("2026-01-15"), warrantyExpiry: new Date('2026-01-15'),
location: "Kaynak Atölyesi", location: 'Kaynak Atölyesi',
departmentId: "4", departmentId: '4',
status: WorkCenterStatusEnum.Operational, status: WorkCenterStatusEnum.Operational,
criticality: CriticalityLevelEnum.High, criticality: CriticalityLevelEnum.High,
specifications: [ specifications: [
{ {
id: "SPEC007", id: 'SPEC007',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Erişim Mesafesi", specificationName: 'Erişim Mesafesi',
specificationValue: "2033", specificationValue: '2033',
unit: "mm", unit: 'mm',
isRequired: true, isRequired: true,
}, },
{ {
id: "SPEC008", id: 'SPEC008',
workCenterId: "EQP004", workCenterId: 'EQP004',
specificationName: "Taşıma Kapasitesi", specificationName: 'Taşıma Kapasitesi',
specificationValue: "60", specificationValue: '60',
unit: "kg", unit: 'kg',
isRequired: true, isRequired: true,
}, },
], ],
@ -358,11 +362,12 @@ export const mockWorkCenters: PmWorkCenter[] = [
workOrders: [], workOrders: [],
downTimeHistory: [], downTimeHistory: [],
isActive: true, isActive: true,
creationTime: new Date("2023-01-15"), creationTime: new Date('2023-01-15'),
lastModificationTime: new Date("2024-01-20"), lastModificationTime: new Date('2024-01-20'),
costPerHour: 85, costPerHour: 85,
setupTime: 20, setupTime: 20,
machineType: "CNC", machineTypeId: '1',
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
capacity: 8, capacity: 8,
}, },
]; ]

View file

@ -42,7 +42,7 @@ export interface BusinessParty {
partyType: PartyType partyType: PartyType
primaryContact?: Contact primaryContact?: Contact
contacts?: Contact[] contacts?: Contact[]
industry?: string industry?: BusinessPartyIndustryEnum
email?: string email?: string
phone?: string phone?: string
website?: string website?: string
@ -77,6 +77,21 @@ export interface BusinessParty {
bankAccounts?: BankAccount[] bankAccounts?: BankAccount[]
} }
export enum BusinessPartyIndustryEnum {
// İş Ortağı Endüstrisi
Technology = 'TECHNOLOGY', // Teknoloji
Healthcare = 'HEALTHCARE', // Sağlık
Finance = 'FINANCE', // Finans
Retail = 'RETAIL', // Perakende
Manufacturing = 'MANUFACTURING', // Üretim
Education = 'EDUCATION', // Eğitim
Construction = 'CONSTRUCTION', // İnşaat
Hospitality = 'HOSPITALITY', // Konaklama
Transportation = 'TRANSPORTATION', // Ulaşım
RealEstate = 'REAL_ESTATE', // Emlak
Other = 'OTHER', // Diğer
}
export enum BusinessPartyStatusEnum { export enum BusinessPartyStatusEnum {
// İş Ortağı Durumu // İş Ortağı Durumu
Prospect = 'PROSPECT', // Potansiyel Prospect = 'PROSPECT', // Potansiyel

View file

@ -205,7 +205,7 @@ export interface FiCheck {
amount: number amount: number
currency: string currency: string
status: CheckStatusEnum status: CheckStatusEnum
type: CheckTypeEnum type: TypeEnum
bankingDate?: Date bankingDate?: Date
collectionDate?: Date collectionDate?: Date
endorsedTo?: string endorsedTo?: string
@ -227,7 +227,7 @@ export interface PromissoryNote {
amount: number amount: number
currency: string currency: string
status: NoteStatusEnum status: NoteStatusEnum
type: NoteTypeEnum // Received or Issued type: TypeEnum // Received or Issued
collectionDate?: Date collectionDate?: Date
endorsedTo?: string endorsedTo?: string
location?: string location?: string
@ -321,7 +321,7 @@ export enum CheckStatusEnum {
Cancelled = 'CANCELLED', // İPTAL EDİLDİ Cancelled = 'CANCELLED', // İPTAL EDİLDİ
} }
export enum CheckTypeEnum { export enum TypeEnum {
Received = 'RECEIVED', // ALINAN Received = 'RECEIVED', // ALINAN
Issued = 'ISSUED', // VERİLEN Issued = 'ISSUED', // VERİLEN
} }
@ -334,11 +334,6 @@ export enum NoteStatusEnum {
Cancelled = 'CANCELLED', // İPTAL EDİLDİ Cancelled = 'CANCELLED', // İPTAL EDİLDİ
} }
export enum NoteTypeEnum {
Received = 'RECEIVED', // Alınan
Issued = 'ISSUED', // Verilen
}
export enum WaybillTypeEnum { export enum WaybillTypeEnum {
Outgoing = 'outgoing', // Çıkış İrsaliyesi Outgoing = 'outgoing', // Çıkış İrsaliyesi
Incoming = 'incoming', // Giriş İrsaliyesi Incoming = 'incoming', // Giriş İrsaliyesi

View file

@ -758,3 +758,20 @@ export enum QuestionTypeEnum {
YesNo = 'YES_NO', // Evet/Hayır YesNo = 'YES_NO', // Evet/Hayır
Scale = 'SCALE', // Ölçek (1-10 gibi) Scale = 'SCALE', // Ölçek (1-10 gibi)
} }
export const getQuestionTypeText = (type: QuestionTypeEnum) => {
switch (type) {
case QuestionTypeEnum.Rating:
return 'Puanlama'
case QuestionTypeEnum.MultipleChoice:
return 'Çoktan Seçmeli'
case QuestionTypeEnum.Text:
return 'Metin'
case QuestionTypeEnum.YesNo:
return 'Evet/Hayır'
case QuestionTypeEnum.Scale:
return 'Ölçek'
default:
return 'Bilinmeyen'
}
}

View file

@ -559,9 +559,11 @@ export enum OrderStatusEnum {
export enum SupplierTypeEnum { export enum SupplierTypeEnum {
// Tedarikçi Türü // Tedarikçi Türü
Material = 'MATERIAL', // Malzeme Manufacturer = 'MANUFACTURER', // Üretici
Service = 'SERVICE', // Hizmet Distributor = 'DISTRIBUTOR', // Distribütör
Both = 'BOTH', // Her ikisi Wholesaler = 'WHOLESALER', // Toptancı
ServiceProvider = 'SERVICE_PROVIDER', // Hizmet Sağlayıcı
Other = 'OTHER', // Diğer
} }
export enum RequisitionStatusEnum { export enum RequisitionStatusEnum {

View file

@ -29,7 +29,8 @@ export interface PmWorkCenter {
capacity: number capacity: number
costPerHour: number costPerHour: number
setupTime: number setupTime: number
machineType: string machineTypeId: string
machineType?: PmMachineType
isActive: boolean isActive: boolean
creationTime: Date creationTime: Date
lastModificationTime: Date lastModificationTime: Date
@ -45,6 +46,14 @@ export interface PmWorkCenterType {
isActive: boolean isActive: boolean
} }
export interface PmMachineType {
// Makina Türü
id: string
code: string
name: string
isActive: boolean
}
export interface PmWorkCenterSpecification { export interface PmWorkCenterSpecification {
// İş Merkezi / Ekipman Özelliği // İş Merkezi / Ekipman Özelliği
id: string id: string

View file

@ -55,7 +55,7 @@ export interface PsProjectPhase {
assignedTeams: string[] assignedTeams: string[]
deliverables: string[] deliverables: string[]
risks: string[] risks: string[]
category: string category: PhaseCategoryEnum
} }
export interface PsProjectTask { export interface PsProjectTask {
@ -172,7 +172,7 @@ export interface PsProjectCostTracking {
plannedDuration: number // days plannedDuration: number // days
actualDuration?: number // days actualDuration?: number // days
progress: number // percentage progress: number // percentage
status: 'ON_TRACK' | 'AT_RISK' | 'DELAYED' | 'COMPLETED' status: ProjectCostTrackingStatus
currency: string currency: string
lastUpdated: Date lastUpdated: Date
} }
@ -255,6 +255,15 @@ export enum ProjectStatusEnum {
Cancelled = 'CANCELLED', // İptal Edildi Cancelled = 'CANCELLED', // İptal Edildi
} }
export enum PhaseCategoryEnum {
// Category of Phase
Planning = 'PLANNING', // Planlama
Development = 'EXECUTION', // Yürütme
Testing = 'MONITORING', // İzleme
Deployment = 'CLOSURE', // Kapanış
Design = 'OTHER', // Diğer
}
export enum PhaseStatusEnum { export enum PhaseStatusEnum {
// Faz Durumu // Faz Durumu
NotStarted = 'NOT_STARTED', // Başlanmadı NotStarted = 'NOT_STARTED', // Başlanmadı
@ -354,3 +363,11 @@ export enum PsDocumentTypeEnum {
Manual = 'MANUAL', // Kılavuz Manual = 'MANUAL', // Kılavuz
Other = 'OTHER', // Diğer Other = 'OTHER', // Diğer
} }
export enum ProjectCostTrackingStatus {
// Proje Maliyet Takibi Durumu
OnTrack = 'ON_TRACK', // Planında
AtRisk = 'AT_RISK', // Riskte
Delayed = 'DELAYED', // Gecikmiş
Completed = 'COMPLETED', // Tamamlandı
}

File diff suppressed because it is too large Load diff

View file

@ -1,159 +1,151 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaSave, FaTimes, FaBuilding } from "react-icons/fa"; import { FaSave, FaTimes, FaBuilding } from 'react-icons/fa'
import { BankAccountTypeEnum } from "../../../types/fi"; import { BankAccountTypeEnum } from '../../../types/fi'
import { BankAccount } from "../../../types/common"; import { BankAccount } from '../../../types/common'
import { getBankAccountTypeText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
interface BankAccountFormProps { interface BankAccountFormProps {
account?: BankAccount; account?: BankAccount
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: (account: Partial<BankAccount>) => void; onSave: (account: Partial<BankAccount>) => void
} }
const BankAccountForm: React.FC<BankAccountFormProps> = ({ const BankAccountForm: React.FC<BankAccountFormProps> = ({ account, isOpen, onClose, onSave }) => {
account,
isOpen,
onClose,
onSave,
}) => {
const [formData, setFormData] = useState<Partial<BankAccount>>({ const [formData, setFormData] = useState<Partial<BankAccount>>({
accountCode: "", accountCode: '',
bankName: "", bankName: '',
branchName: "", branchName: '',
accountNumber: "", accountNumber: '',
iban: "", iban: '',
accountType: BankAccountTypeEnum.Current, accountType: BankAccountTypeEnum.Current,
currency: "TRY", currency: 'TRY',
balance: 0, balance: 0,
overdraftLimit: 0, overdraftLimit: 0,
dailyTransferLimit: 0, dailyTransferLimit: 0,
contactPerson: "", contactPerson: '',
phone: "", phone: '',
isActive: true, isActive: true,
}); })
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({})
useEffect(() => { useEffect(() => {
if (account) { if (account) {
setFormData(account); setFormData(account)
} else { } else {
setFormData({ setFormData({
accountCode: "", accountCode: '',
bankName: "", bankName: '',
branchName: "", branchName: '',
accountNumber: "", accountNumber: '',
iban: "", iban: '',
accountType: BankAccountTypeEnum.Current, accountType: BankAccountTypeEnum.Current,
currency: "TRY", currency: 'TRY',
balance: 0, balance: 0,
overdraftLimit: 0, overdraftLimit: 0,
dailyTransferLimit: 0, dailyTransferLimit: 0,
contactPerson: "", contactPerson: '',
phone: "", phone: '',
isActive: true, isActive: true,
}); })
} }
setErrors({}); setErrors({})
}, [account, isOpen]); }, [account, isOpen])
const validateForm = () => { const validateForm = () => {
const newErrors: Record<string, string> = {}; const newErrors: Record<string, string> = {}
if (!formData.accountCode?.trim()) { if (!formData.accountCode?.trim()) {
newErrors.accountCode = "Hesap kodu gereklidir"; newErrors.accountCode = 'Hesap kodu gereklidir'
} }
if (!formData.bankName?.trim()) { if (!formData.bankName?.trim()) {
newErrors.bankName = "Banka adı gereklidir"; newErrors.bankName = 'Banka adı gereklidir'
} }
if (!formData.branchName?.trim()) { if (!formData.branchName?.trim()) {
newErrors.branchName = "Şube adı gereklidir"; newErrors.branchName = 'Şube adı gereklidir'
} }
if (!formData.accountNumber?.trim()) { if (!formData.accountNumber?.trim()) {
newErrors.accountNumber = "Hesap numarası gereklidir"; newErrors.accountNumber = 'Hesap numarası gereklidir'
} }
if (!formData.iban?.trim()) { if (!formData.iban?.trim()) {
newErrors.iban = "IBAN gereklidir"; newErrors.iban = 'IBAN gereklidir'
} else if (formData.iban.length < 26) { } else if (formData.iban.length < 26) {
newErrors.iban = "IBAN geçerli formatta olmalıdır"; newErrors.iban = 'IBAN geçerli formatta olmalıdır'
} }
if (!formData.currency?.trim()) { if (!formData.currency?.trim()) {
newErrors.currency = "Para birimi gereklidir"; newErrors.currency = 'Para birimi gereklidir'
} }
if ( if (formData.dailyTransferLimit !== undefined && formData.dailyTransferLimit < 0) {
formData.dailyTransferLimit !== undefined && newErrors.dailyTransferLimit = 'Günlük transfer limiti negatif olamaz'
formData.dailyTransferLimit < 0
) {
newErrors.dailyTransferLimit = "Günlük transfer limiti negatif olamaz";
} }
if (formData.overdraftLimit !== undefined && formData.overdraftLimit < 0) { if (formData.overdraftLimit !== undefined && formData.overdraftLimit < 0) {
newErrors.overdraftLimit = "Kredi limiti negatif olamaz"; newErrors.overdraftLimit = 'Kredi limiti negatif olamaz'
} }
setErrors(newErrors); setErrors(newErrors)
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (validateForm()) { if (validateForm()) {
onSave(formData); onSave(formData)
} }
}; }
const handleInputChange = ( const handleInputChange = (
e: React.ChangeEvent< e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
>
) => { ) => {
const { name, value, type } = e.target; const { name, value, type } = e.target
const parsedValue = type === "number" ? parseFloat(value) || 0 : value; const parsedValue = type === 'number' ? parseFloat(value) || 0 : value
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: parsedValue, [name]: parsedValue,
})); }))
// Clear error when user starts typing // Clear error when user starts typing
if (errors[name]) { if (errors[name]) {
setErrors((prev) => ({ setErrors((prev) => ({
...prev, ...prev,
[name]: "", [name]: '',
})); }))
} }
}; }
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, checked } = e.target; const { name, checked } = e.target
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: checked, [name]: checked,
})); }))
}; }
const handleIbanChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleIbanChange = (e: React.ChangeEvent<HTMLInputElement>) => {
let value = e.target.value; let value = e.target.value
// Sadece harf ve rakam kalsın // Sadece harf ve rakam kalsın
value = value.replace(/[^A-Za-z0-9]/g, ""); value = value.replace(/[^A-Za-z0-9]/g, '')
// 4 karakterde bir boşluk ekle // 4 karakterde bir boşluk ekle
value = value.replace(/(.{4})/g, "$1 ").trim(); value = value.replace(/(.{4})/g, '$1 ').trim()
setFormData({ setFormData({
...formData, ...formData,
iban: value, iban: value,
}); })
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
@ -162,7 +154,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
<div className="flex items-center gap-2.5"> <div className="flex items-center gap-2.5">
<FaBuilding className="w-5 h-5 text-blue-600" /> <FaBuilding className="w-5 h-5 text-blue-600" />
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{account ? "Banka Hesabını Düzenle" : "Yeni Banka Hesabı"} {account ? 'Banka Hesabını Düzenle' : 'Yeni Banka Hesabı'}
</h2> </h2>
</div> </div>
<button <button
@ -182,80 +174,67 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
</h3> </h3>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Hesap Kodu *</label>
Hesap Kodu *
</label>
<input <input
type="text" type="text"
name="accountCode" name="accountCode"
value={formData.accountCode || ""} value={formData.accountCode || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.accountCode ? "border-red-500" : "border-gray-300" errors.accountCode ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Örn: BANKA001" placeholder="Örn: BANKA001"
/> />
{errors.accountCode && ( {errors.accountCode && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.accountCode}</p>
{errors.accountCode}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
Banka Adı *
</label>
<input <input
type="text" type="text"
name="bankName" name="bankName"
value={formData.bankName || ""} value={formData.bankName || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.bankName ? "border-red-500" : "border-gray-300" errors.bankName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Örn: İş Bankası" placeholder="Örn: İş Bankası"
/> />
{errors.bankName && ( {errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
<p className="text-red-500 text-xs mt-1">{errors.bankName}</p>
)}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı *</label>
Şube Adı *
</label>
<input <input
type="text" type="text"
name="branchName" name="branchName"
value={formData.branchName || ""} value={formData.branchName || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.branchName ? "border-red-500" : "border-gray-300" errors.branchName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Örn: Levent Şubesi" placeholder="Örn: Levent Şubesi"
/> />
{errors.branchName && ( {errors.branchName && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.branchName}</p>
{errors.branchName}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Hesap Türü</label>
Hesap Türü
</label>
<select <select
name="accountType" name="accountType"
value={formData.accountType || BankAccountTypeEnum.Current} value={formData.accountType || BankAccountTypeEnum.Current}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={BankAccountTypeEnum.Current}>Vadesiz</option> {Object.values(BankAccountTypeEnum).map((type) => (
<option value={BankAccountTypeEnum.Deposit}>Vadeli</option> <option key={type} value={type}>
<option value={BankAccountTypeEnum.Credit}>Kredi</option> {getBankAccountTypeText(type)}
<option value={BankAccountTypeEnum.Foreign}>Döviz</option> </option>
))}
</select> </select>
</div> </div>
@ -265,20 +244,19 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
</label> </label>
<select <select
name="currency" name="currency"
value={formData.currency || "TRY"} value={formData.currency || 'TRY'}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.currency ? "border-red-500" : "border-gray-300" errors.currency ? 'border-red-500' : 'border-gray-300'
}`} }`}
> >
<option value="TRY">TRY - Türk Lirası</option> {mockCurrencies.map((cur) => (
<option value="USD">USD - Amerikan Doları</option> <option key={cur.value} value={cur.value}>
<option value="EUR">EUR - Euro</option> {cur.value} - {cur.label}
<option value="GBP">GBP - İngiliz Sterlini</option> </option>
))}
</select> </select>
{errors.currency && ( {errors.currency && <p className="text-red-500 text-xs mt-1">{errors.currency}</p>}
<p className="text-red-500 text-xs mt-1">{errors.currency}</p>
)}
</div> </div>
</div> </div>
@ -295,38 +273,32 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
<input <input
type="text" type="text"
name="accountNumber" name="accountNumber"
value={formData.accountNumber || ""} value={formData.accountNumber || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.accountNumber ? "border-red-500" : "border-gray-300" errors.accountNumber ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="1234567890" placeholder="1234567890"
/> />
{errors.accountNumber && ( {errors.accountNumber && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.accountNumber}</p>
{errors.accountNumber}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">IBAN *</label>
IBAN *
</label>
<input <input
type="text" type="text"
name="iban" name="iban"
value={formData.iban || ""} value={formData.iban || ''}
onChange={handleIbanChange} onChange={handleIbanChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono ${
errors.iban ? "border-red-500" : "border-gray-300" errors.iban ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="TR12 0006 4000 0011 2345 6789 01" placeholder="TR12 0006 4000 0011 2345 6789 01"
maxLength={34} maxLength={34}
/> />
{errors.iban && ( {errors.iban && <p className="text-red-500 text-xs mt-1">{errors.iban}</p>}
<p className="text-red-500 text-xs mt-1">{errors.iban}</p>
)}
</div> </div>
<div> <div>
@ -344,24 +316,20 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Kredi Limiti</label>
Kredi Limiti
</label>
<input <input
type="number" type="number"
name="overdraftLimit" name="overdraftLimit"
value={formData.overdraftLimit || 0} value={formData.overdraftLimit || 0}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.overdraftLimit ? "border-red-500" : "border-gray-300" errors.overdraftLimit ? 'border-red-500' : 'border-gray-300'
}`} }`}
step="0.01" step="0.01"
min="0" min="0"
/> />
{errors.overdraftLimit && ( {errors.overdraftLimit && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.overdraftLimit}</p>
{errors.overdraftLimit}
</p>
)} )}
</div> </div>
@ -375,17 +343,13 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
value={formData.dailyTransferLimit || 0} value={formData.dailyTransferLimit || 0}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.dailyTransferLimit errors.dailyTransferLimit ? 'border-red-500' : 'border-gray-300'
? "border-red-500"
: "border-gray-300"
}`} }`}
step="0.01" step="0.01"
min="0" min="0"
/> />
{errors.dailyTransferLimit && ( {errors.dailyTransferLimit && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.dailyTransferLimit}</p>
{errors.dailyTransferLimit}
</p>
)} )}
</div> </div>
</div> </div>
@ -404,7 +368,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
<input <input
type="text" type="text"
name="contactPerson" name="contactPerson"
value={formData.contactPerson || ""} value={formData.contactPerson || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Ad Soyad" placeholder="Ad Soyad"
@ -412,13 +376,11 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
Telefon
</label>
<input <input
type="tel" type="tel"
name="phone" name="phone"
value={formData.phone || ""} value={formData.phone || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="+90 212 555 1234" placeholder="+90 212 555 1234"
@ -434,9 +396,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
onChange={handleCheckboxChange} onChange={handleCheckboxChange}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/> />
<label className="ml-2 block text-sm text-gray-700"> <label className="ml-2 block text-sm text-gray-700">Hesap aktif</label>
Hesap aktif
</label>
</div> </div>
</div> </div>
</div> </div>
@ -455,13 +415,13 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors" className="flex items-center gap-2 px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{account ? "Güncelle" : "Kaydet"} {account ? 'Güncelle' : 'Kaydet'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default BankAccountForm; export default BankAccountForm

View file

@ -1,20 +1,15 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaCreditCard, FaSave, FaTimes } from "react-icons/fa"; import { FaCreditCard, FaSave, FaTimes } from 'react-icons/fa'
import { import { FiCheck, TypeEnum, CheckStatusEnum, FiCurrentAccount } from '../../../types/fi'
FiCheck, import { getCheckStatusText, getTypeText } from '@/utils/erp'
CheckTypeEnum, import { mockCurrencies } from '@/mocks/mockCurrencies'
CheckStatusEnum,
FiCurrentAccount,
} from "../../../types/fi";
interface CheckFormProps { interface CheckFormProps {
check?: FiCheck; check?: FiCheck
currentAccounts: FiCurrentAccount[]; currentAccounts: FiCurrentAccount[]
onSave: ( onSave: (check: Omit<FiCheck, 'id' | 'creationTime' | 'lastModificationTime'>) => void
check: Omit<FiCheck, "id" | "creationTime" | "lastModificationTime"> onCancel: () => void
) => void; isOpen: boolean
onCancel: () => void;
isOpen: boolean;
} }
const CheckForm: React.FC<CheckFormProps> = ({ const CheckForm: React.FC<CheckFormProps> = ({
@ -25,23 +20,23 @@ const CheckForm: React.FC<CheckFormProps> = ({
isOpen, isOpen,
}) => { }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
checkNumber: "", checkNumber: '',
bankName: "", bankName: '',
branchName: "", branchName: '',
accountNumber: "", accountNumber: '',
drawerName: "", drawerName: '',
payeeName: "", payeeName: '',
currentAccountId: "", currentAccountId: '',
issueDate: new Date().toISOString().split("T")[0], issueDate: new Date().toISOString().split('T')[0],
dueDate: new Date().toISOString().split("T")[0], dueDate: new Date().toISOString().split('T')[0],
amount: 0, amount: 0,
currency: "TRY", currency: 'TRY',
status: CheckStatusEnum.InHand, status: CheckStatusEnum.InHand,
type: CheckTypeEnum.Received, type: TypeEnum.Received,
notes: "", notes: '',
}); })
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({})
useEffect(() => { useEffect(() => {
if (check) { if (check) {
@ -52,64 +47,64 @@ const CheckForm: React.FC<CheckFormProps> = ({
accountNumber: check.accountNumber, accountNumber: check.accountNumber,
drawerName: check.drawerName, drawerName: check.drawerName,
payeeName: check.payeeName, payeeName: check.payeeName,
currentAccountId: check.currentAccountId || "", currentAccountId: check.currentAccountId || '',
issueDate: new Date(check.issueDate).toISOString().split("T")[0], issueDate: new Date(check.issueDate).toISOString().split('T')[0],
dueDate: new Date(check.dueDate).toISOString().split("T")[0], dueDate: new Date(check.dueDate).toISOString().split('T')[0],
amount: check.amount, amount: check.amount,
currency: check.currency, currency: check.currency,
status: check.status, status: check.status,
type: check.type, type: check.type,
notes: check.notes || "", notes: check.notes || '',
}); })
} else { } else {
setFormData({ setFormData({
checkNumber: "", checkNumber: '',
bankName: "", bankName: '',
branchName: "", branchName: '',
accountNumber: "", accountNumber: '',
drawerName: "", drawerName: '',
payeeName: "", payeeName: '',
currentAccountId: "", currentAccountId: '',
issueDate: new Date().toISOString().split("T")[0], issueDate: new Date().toISOString().split('T')[0],
dueDate: new Date().toISOString().split("T")[0], dueDate: new Date().toISOString().split('T')[0],
amount: 0, amount: 0,
currency: "TRY", currency: 'TRY',
status: CheckStatusEnum.InHand, status: CheckStatusEnum.InHand,
type: CheckTypeEnum.Received, type: TypeEnum.Received,
notes: "", notes: '',
}); })
} }
setErrors({}); setErrors({})
}, [check, isOpen]); }, [check, isOpen])
const validateForm = () => { const validateForm = () => {
const newErrors: Record<string, string> = {}; const newErrors: Record<string, string> = {}
if (!formData.checkNumber.trim()) { if (!formData.checkNumber.trim()) {
newErrors.checkNumber = "Çek numarası gereklidir"; newErrors.checkNumber = 'Çek numarası gereklidir'
} }
if (!formData.bankName.trim()) { if (!formData.bankName.trim()) {
newErrors.bankName = "Banka adı gereklidir"; newErrors.bankName = 'Banka adı gereklidir'
} }
if (!formData.drawerName.trim()) { if (!formData.drawerName.trim()) {
newErrors.drawerName = "Keşideci adı gereklidir"; newErrors.drawerName = 'Keşideci adı gereklidir'
} }
if (!formData.payeeName.trim()) { if (!formData.payeeName.trim()) {
newErrors.payeeName = "Lehtar adı gereklidir"; newErrors.payeeName = 'Lehtar adı gereklidir'
} }
if (formData.amount <= 0) { if (formData.amount <= 0) {
newErrors.amount = "Tutar 0'dan büyük olmalıdır"; newErrors.amount = "Tutar 0'dan büyük olmalıdır"
} }
if (new Date(formData.dueDate) < new Date(formData.issueDate)) { if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
newErrors.dueDate = "Vade tarihi düzenleme tarihinden sonra olmalıdır"; newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
} }
setErrors(newErrors); setErrors(newErrors)
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (validateForm()) { if (validateForm()) {
const checkData = { const checkData = {
...formData, ...formData,
@ -118,22 +113,22 @@ const CheckForm: React.FC<CheckFormProps> = ({
currentAccount: formData.currentAccountId currentAccount: formData.currentAccountId
? currentAccounts.find((acc) => acc.id === formData.currentAccountId) ? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
: undefined, : undefined,
}; }
onSave(checkData); onSave(checkData)
} }
}; }
const handleInputChange = ( const handleInputChange = (
field: string, field: string,
value: string | number | CheckTypeEnum | CheckStatusEnum value: string | number | TypeEnum | CheckStatusEnum,
) => { ) => {
setFormData((prev) => ({ ...prev, [field]: value })); setFormData((prev) => ({ ...prev, [field]: value }))
if (errors[field]) { if (errors[field]) {
setErrors((prev) => ({ ...prev, [field]: "" })); setErrors((prev) => ({ ...prev, [field]: '' }))
} }
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
@ -142,13 +137,10 @@ const CheckForm: React.FC<CheckFormProps> = ({
<div className="flex items-center gap-2.5"> <div className="flex items-center gap-2.5">
<FaCreditCard className="w-5 h-5 text-blue-600" /> <FaCreditCard className="w-5 h-5 text-blue-600" />
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{check ? "Çek Düzenle" : "Yeni Çek"} {check ? 'Çek Düzenle' : 'Yeni Çek'}
</h2> </h2>
</div> </div>
<button <button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
onClick={onCancel}
className="p-2 hover:bg-gray-100 rounded-md"
>
<FaTimes className="w-5 h-5 text-gray-500" /> <FaTimes className="w-5 h-5 text-gray-500" />
</button> </button>
</div> </div>
@ -157,102 +149,76 @@ const CheckForm: React.FC<CheckFormProps> = ({
{/* Çek Bilgileri */} {/* Çek Bilgileri */}
<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-3 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Çek Numarası *</label>
Çek Numarası *
</label>
<input <input
type="text" type="text"
value={formData.checkNumber} value={formData.checkNumber}
onChange={(e) => onChange={(e) => handleInputChange('checkNumber', e.target.value)}
handleInputChange("checkNumber", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.checkNumber ? "border-red-500" : "border-gray-300" errors.checkNumber ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Çek numarasını giriniz" placeholder="Çek numarasını giriniz"
/> />
{errors.checkNumber && ( {errors.checkNumber && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.checkNumber}</p>
{errors.checkNumber}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
Tür *
</label>
<select <select
value={formData.type} value={formData.type}
onChange={(e) => onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
handleInputChange("type", e.target.value as CheckTypeEnum)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={CheckTypeEnum.Received}>Alınan Çek</option> {Object.values(TypeEnum).map((type) => (
<option value={CheckTypeEnum.Issued}>Verilen Çek</option> <option key={type} value={type}>
{getTypeText(type)}
</option>
))}
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
Durum
</label>
<select <select
value={formData.status} value={formData.status}
onChange={(e) => onChange={(e) => handleInputChange('status', e.target.value as CheckStatusEnum)}
handleInputChange("status", e.target.value as CheckStatusEnum)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={CheckStatusEnum.InHand}>Elde</option> {Object.values(CheckStatusEnum).map((status) => (
<option value={CheckStatusEnum.Deposited}> <option key={status} value={status}>
Bankaya Verildi {getCheckStatusText(status)}
</option> </option>
<option value={CheckStatusEnum.Collected}>Tahsil Edildi</option> ))}
<option value={CheckStatusEnum.Bounced}>Karşılıksız</option>
<option value={CheckStatusEnum.Endorsed}>Ciro Edildi</option>
<option value={CheckStatusEnum.Cancelled}>İptal</option>
</select> </select>
</div> </div>
</div> </div>
{/* Banka Bilgileri */} {/* Banka Bilgileri */}
<div className="bg-gray-50 p-3 rounded-lg"> <div className="bg-gray-50 p-3 rounded-lg">
<h3 className="text-base font-medium text-gray-900 mb-3"> <h3 className="text-base font-medium text-gray-900 mb-3">Banka Bilgileri</h3>
Banka Bilgileri
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3"> <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
Banka Adı *
</label>
<input <input
type="text" type="text"
value={formData.bankName} value={formData.bankName}
onChange={(e) => onChange={(e) => handleInputChange('bankName', e.target.value)}
handleInputChange("bankName", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.bankName ? "border-red-500" : "border-gray-300" errors.bankName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Banka adını giriniz" placeholder="Banka adını giriniz"
/> />
{errors.bankName && ( {errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
<p className="text-red-500 text-xs mt-1">{errors.bankName}</p>
)}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı</label>
Şube Adı
</label>
<input <input
type="text" type="text"
value={formData.branchName} value={formData.branchName}
onChange={(e) => onChange={(e) => handleInputChange('branchName', e.target.value)}
handleInputChange("branchName", e.target.value)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Şube adını giriniz" placeholder="Şube adını giriniz"
/> />
@ -265,9 +231,7 @@ const CheckForm: React.FC<CheckFormProps> = ({
<input <input
type="text" type="text"
value={formData.accountNumber} value={formData.accountNumber}
onChange={(e) => onChange={(e) => handleInputChange('accountNumber', e.target.value)}
handleInputChange("accountNumber", e.target.value)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Hesap numarasını giriniz" placeholder="Hesap numarasını giriniz"
/> />
@ -277,63 +241,45 @@ const CheckForm: React.FC<CheckFormProps> = ({
{/* Taraf Bilgileri */} {/* Taraf Bilgileri */}
<div className="bg-gray-50 p-3 rounded-lg"> <div className="bg-gray-50 p-3 rounded-lg">
<h3 className="text-base font-medium text-gray-900 mb-3"> <h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
Taraf Bilgileri
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3"> <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
Keşideci *
</label>
<input <input
type="text" type="text"
value={formData.drawerName} value={formData.drawerName}
onChange={(e) => onChange={(e) => handleInputChange('drawerName', e.target.value)}
handleInputChange("drawerName", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.drawerName ? "border-red-500" : "border-gray-300" errors.drawerName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Keşideci adını giriniz" placeholder="Keşideci adını giriniz"
/> />
{errors.drawerName && ( {errors.drawerName && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
{errors.drawerName}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
Lehtar *
</label>
<input <input
type="text" type="text"
value={formData.payeeName} value={formData.payeeName}
onChange={(e) => onChange={(e) => handleInputChange('payeeName', e.target.value)}
handleInputChange("payeeName", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.payeeName ? "border-red-500" : "border-gray-300" errors.payeeName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Lehtar adını giriniz" placeholder="Lehtar adını giriniz"
/> />
{errors.payeeName && ( {errors.payeeName && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
{errors.payeeName}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
Cari Hesap
</label>
<select <select
value={formData.currentAccountId} value={formData.currentAccountId}
onChange={(e) => onChange={(e) => handleInputChange('currentAccountId', e.target.value)}
handleInputChange("currentAccountId", e.target.value)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Cari hesap seçiniz</option> <option value="">Cari hesap seçiniz</option>
@ -350,39 +296,33 @@ const CheckForm: React.FC<CheckFormProps> = ({
{/* Tutar ve Tarih Bilgileri */} {/* Tutar ve Tarih Bilgileri */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
Tutar *
</label>
<input <input
type="number" type="number"
step="0.01" step="0.01"
min="0" min="0"
value={formData.amount} value={formData.amount}
onChange={(e) => onChange={(e) => handleInputChange('amount', parseFloat(e.target.value) || 0)}
handleInputChange("amount", parseFloat(e.target.value) || 0)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.amount ? "border-red-500" : "border-gray-300" errors.amount ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="0.00" placeholder="0.00"
/> />
{errors.amount && ( {errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
<p className="text-red-500 text-xs mt-1">{errors.amount}</p>
)}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
Para Birimi
</label>
<select <select
value={formData.currency} value={formData.currency}
onChange={(e) => handleInputChange("currency", e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
@ -393,37 +333,31 @@ const CheckForm: React.FC<CheckFormProps> = ({
<input <input
type="date" type="date"
value={formData.issueDate} value={formData.issueDate}
onChange={(e) => handleInputChange("issueDate", e.target.value)} onChange={(e) => handleInputChange('issueDate', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
Vade Tarihi *
</label>
<input <input
type="date" type="date"
value={formData.dueDate} value={formData.dueDate}
onChange={(e) => handleInputChange("dueDate", e.target.value)} onChange={(e) => handleInputChange('dueDate', e.target.value)}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.dueDate ? "border-red-500" : "border-gray-300" errors.dueDate ? 'border-red-500' : 'border-gray-300'
}`} }`}
/> />
{errors.dueDate && ( {errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
<p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>
)}
</div> </div>
</div> </div>
{/* Notlar */} {/* Notlar */}
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
Notlar
</label>
<textarea <textarea
value={formData.notes} value={formData.notes}
onChange={(e) => handleInputChange("notes", e.target.value)} onChange={(e) => handleInputChange('notes', e.target.value)}
rows={3} rows={3}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Ek notlar..." placeholder="Ek notlar..."
@ -444,13 +378,13 @@ const CheckForm: React.FC<CheckFormProps> = ({
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors" className="flex items-center gap-2 px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{check ? "Güncelle" : "Kaydet"} {check ? 'Güncelle' : 'Kaydet'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default CheckForm; export default CheckForm

View file

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
import { import {
FaCreditCard, FaCreditCard,
FaFileAlt, FaFileAlt,
@ -7,113 +7,84 @@ import {
FaUser, FaUser,
FaMoneyBillWave, FaMoneyBillWave,
FaInfoCircle, FaInfoCircle,
} from "react-icons/fa"; } from 'react-icons/fa'
import { import {
FiCheck, FiCheck,
PromissoryNote, PromissoryNote,
CheckStatusEnum, CheckStatusEnum,
NoteStatusEnum, NoteStatusEnum,
CheckTypeEnum, TypeEnum,
NoteTypeEnum, } from '../../../types/fi'
} from "../../../types/fi"; import {
getCheckStatusColor,
getCheckStatusText,
getNoteStatusColor,
getNoteStatusText,
} from '@/utils/erp'
interface CheckNoteDetailsProps { interface CheckNoteDetailsProps {
item: FiCheck | PromissoryNote; item: FiCheck | PromissoryNote
onClose: () => void; onClose: () => void
isOpen: boolean; isOpen: boolean
} }
const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({ item, onClose, isOpen }) => {
item, if (!isOpen) return null
onClose,
isOpen,
}) => {
if (!isOpen) return null;
const isCheck = "checkNumber" in item; const isCheck = 'checkNumber' in item
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return amount.toLocaleString("tr-TR", { return amount.toLocaleString('tr-TR', {
style: "currency", style: 'currency',
currency: "TRY", currency: 'TRY',
minimumFractionDigits: 2, minimumFractionDigits: 2,
}); })
}; }
const getStatusLabel = (status: CheckStatusEnum | NoteStatusEnum) => { const getStatusLabel = (status: CheckStatusEnum | NoteStatusEnum) => {
if (isCheck) { if (isCheck) {
const statusLabels = { return getCheckStatusText(status as CheckStatusEnum)
[CheckStatusEnum.InHand]: "Elde",
[CheckStatusEnum.Deposited]: "Bankaya Verildi",
[CheckStatusEnum.Collected]: "Tahsil Edildi",
[CheckStatusEnum.Bounced]: "Karşılıksız",
[CheckStatusEnum.Endorsed]: "Ciro Edildi",
[CheckStatusEnum.Cancelled]: "İptal",
};
return statusLabels[status as CheckStatusEnum];
} else { } else {
const statusLabels = { return getNoteStatusText(status as NoteStatusEnum)
[NoteStatusEnum.InHand]: "Elde",
[NoteStatusEnum.Collected]: "Tahsil Edildi",
[NoteStatusEnum.Overdue]: "Vadesi Geçmiş",
[NoteStatusEnum.Endorsed]: "Ciro Edildi",
[NoteStatusEnum.Cancelled]: "İptal",
};
return statusLabels[status as NoteStatusEnum];
} }
}; }
const getStatusColor = (status: CheckStatusEnum | NoteStatusEnum) => { const getStatusColor = (status: CheckStatusEnum | NoteStatusEnum) => {
if (isCheck) { if (isCheck) {
const statusColors = { return getCheckStatusColor(status as CheckStatusEnum)
[CheckStatusEnum.InHand]: "bg-blue-100 text-blue-800",
[CheckStatusEnum.Deposited]: "bg-yellow-100 text-yellow-800",
[CheckStatusEnum.Collected]: "bg-green-100 text-green-800",
[CheckStatusEnum.Bounced]: "bg-red-100 text-red-800",
[CheckStatusEnum.Endorsed]: "bg-purple-100 text-purple-800",
[CheckStatusEnum.Cancelled]: "bg-gray-100 text-gray-800",
};
return statusColors[status as CheckStatusEnum];
} else { } else {
const statusColors = { return getNoteStatusColor(status as NoteStatusEnum)
[NoteStatusEnum.InHand]: "bg-blue-100 text-blue-800",
[NoteStatusEnum.Collected]: "bg-green-100 text-green-800",
[NoteStatusEnum.Overdue]: "bg-red-100 text-red-800",
[NoteStatusEnum.Endorsed]: "bg-purple-100 text-purple-800",
[NoteStatusEnum.Cancelled]: "bg-gray-100 text-gray-800",
};
return statusColors[status as NoteStatusEnum];
} }
}; }
const getTypeLabel = (type: CheckTypeEnum | NoteTypeEnum) => { const getTypeLabel = (type: TypeEnum) => {
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) { if (type === TypeEnum.Received) {
return "Alınan"; return 'Alınan'
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) { } else if (type === TypeEnum.Issued) {
return "Verilen"; return 'Verilen'
} }
return "Bilinmeyen"; return 'Bilinmeyen'
}; }
const getTypeColor = (type: CheckTypeEnum | NoteTypeEnum) => { const getTypeColor = (type: TypeEnum) => {
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) { if (type === TypeEnum.Received) {
return "bg-green-100 text-green-800"; return 'bg-green-100 text-green-800'
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) { } else if (type === TypeEnum.Issued) {
return "bg-orange-100 text-orange-800"; return 'bg-orange-100 text-orange-800'
} }
return "bg-gray-100 text-gray-800"; return 'bg-gray-100 text-gray-800'
}; }
const getDaysUntilDue = (dueDate: Date) => { const getDaysUntilDue = (dueDate: Date) => {
const today = new Date(); const today = new Date()
const due = new Date(dueDate); const due = new Date(dueDate)
const diffTime = due.getTime() - today.getTime(); const diffTime = due.getTime() - today.getTime()
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
return diffDays; return diffDays
}; }
const daysUntilDue = getDaysUntilDue(item.dueDate); const daysUntilDue = getDaysUntilDue(item.dueDate)
const isOverdue = daysUntilDue < 0; const isOverdue = daysUntilDue < 0
const isDueSoon = daysUntilDue <= 7 && daysUntilDue >= 0; const isDueSoon = daysUntilDue <= 7 && daysUntilDue >= 0
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
@ -127,19 +98,14 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
)} )}
<div> <div>
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{isCheck ? "Çek Detayları" : "Senet Detayları"} {isCheck ? 'Çek Detayları' : 'Senet Detayları'}
</h2> </h2>
<p className="text-sm text-gray-600"> <p className="text-sm text-gray-600">
{isCheck {isCheck ? (item as FiCheck).checkNumber : (item as PromissoryNote).noteNumber}
? (item as FiCheck).checkNumber
: (item as PromissoryNote).noteNumber}
</p> </p>
</div> </div>
</div> </div>
<button <button onClick={onClose} className="p-2 hover:bg-gray-100 rounded-md">
onClick={onClose}
className="p-2 hover:bg-gray-100 rounded-md"
>
<FaTimes className="w-5 h-5 text-gray-500" /> <FaTimes className="w-5 h-5 text-gray-500" />
</button> </button>
</div> </div>
@ -149,15 +115,13 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor(
item.status item.status,
)}`} )}`}
> >
{getStatusLabel(item.status)} {getStatusLabel(item.status)}
</span> </span>
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getTypeColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getTypeColor(item.type)}`}
item.type
)}`}
> >
{getTypeLabel(item.type)} {getTypeLabel(item.type)}
</span> </span>
@ -183,13 +147,9 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
</h3> </h3>
<div className="space-y-2 text-sm"> <div className="space-y-2 text-sm">
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600"> <span className="text-gray-600">{isCheck ? 'Çek No:' : 'Senet No:'}</span>
{isCheck ? "Çek No:" : "Senet No:"}
</span>
<span className="font-medium"> <span className="font-medium">
{isCheck {isCheck ? (item as FiCheck).checkNumber : (item as PromissoryNote).noteNumber}
? (item as FiCheck).checkNumber
: (item as PromissoryNote).noteNumber}
</span> </span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
@ -205,9 +165,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
{!isCheck && (item as PromissoryNote).location && ( {!isCheck && (item as PromissoryNote).location && (
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600">Konum:</span> <span className="text-gray-600">Konum:</span>
<span className="font-medium"> <span className="font-medium">{(item as PromissoryNote).location}</span>
{(item as PromissoryNote).location}
</span>
</div> </div>
)} )}
</div> </div>
@ -223,35 +181,29 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600">Düzenleme Tarihi:</span> <span className="text-gray-600">Düzenleme Tarihi:</span>
<span className="font-medium"> <span className="font-medium">
{new Date(item.issueDate).toLocaleDateString("tr-TR")} {new Date(item.issueDate).toLocaleDateString('tr-TR')}
</span> </span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600">Vade Tarihi:</span> <span className="text-gray-600">Vade Tarihi:</span>
<span <span
className={`font-medium ${ className={`font-medium ${
isOverdue isOverdue ? 'text-red-600' : isDueSoon ? 'text-orange-600' : 'text-gray-900'
? "text-red-600"
: isDueSoon
? "text-orange-600"
: "text-gray-900"
}`} }`}
> >
{new Date(item.dueDate).toLocaleDateString("tr-TR")} {new Date(item.dueDate).toLocaleDateString('tr-TR')}
</span> </span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600">Oluşturma Tarihi:</span> <span className="text-gray-600">Oluşturma Tarihi:</span>
<span className="font-medium"> <span className="font-medium">
{new Date(item.creationTime).toLocaleDateString("tr-TR")} {new Date(item.creationTime).toLocaleDateString('tr-TR')}
</span> </span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600">Son Güncelleme:</span> <span className="text-gray-600">Son Güncelleme:</span>
<span className="font-medium"> <span className="font-medium">
{new Date(item.lastModificationTime).toLocaleDateString( {new Date(item.lastModificationTime).toLocaleDateString('tr-TR')}
"tr-TR"
)}
</span> </span>
</div> </div>
</div> </div>
@ -267,24 +219,16 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
</h3> </h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm"> <div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm">
<div> <div>
<span className="text-gray-600 block text-sm"> <span className="text-gray-600 block text-sm">Banka Adı:</span>
Banka Adı: <span className="font-medium">{(item as FiCheck).bankName}</span>
</span>
<span className="font-medium">
{(item as FiCheck).bankName}
</span>
</div> </div>
<div> <div>
<span className="text-gray-600 block text-sm">Şube Adı:</span> <span className="text-gray-600 block text-sm">Şube Adı:</span>
<span className="font-medium"> <span className="font-medium">{(item as FiCheck).branchName}</span>
{(item as FiCheck).branchName}
</span>
</div> </div>
<div> <div>
<span className="text-gray-600 block text-sm">Hesap No:</span> <span className="text-gray-600 block text-sm">Hesap No:</span>
<span className="font-medium"> <span className="font-medium">{(item as FiCheck).accountNumber}</span>
{(item as FiCheck).accountNumber}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -308,12 +252,9 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
</div> </div>
{item.currentAccount && ( {item.currentAccount && (
<div className="mt-3 p-2 bg-blue-50 rounded-lg text-sm"> <div className="mt-3 p-2 bg-blue-50 rounded-lg text-sm">
<span className="text-gray-600 block text-sm"> <span className="text-gray-600 block text-sm">Bağlı Cari Hesap:</span>
Bağlı Cari Hesap:
</span>
<span className="font-medium text-blue-600"> <span className="font-medium text-blue-600">
{item.currentAccount.accountCode} -{" "} {item.currentAccount.accountCode} - {item.currentAccount.accountCode}
{item.currentAccount.accountCode}
</span> </span>
</div> </div>
)} )}
@ -330,9 +271,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
<div className="flex justify-between items-center p-3 bg-yellow-50 rounded-lg"> <div className="flex justify-between items-center p-3 bg-yellow-50 rounded-lg">
<span className="text-gray-700">Bankaya Verilme Tarihi:</span> <span className="text-gray-700">Bankaya Verilme Tarihi:</span>
<span className="font-medium"> <span className="font-medium">
{new Date((item as FiCheck).bankingDate!).toLocaleDateString( {new Date((item as FiCheck).bankingDate!).toLocaleDateString('tr-TR')}
"tr-TR"
)}
</span> </span>
</div> </div>
)} )}
@ -340,35 +279,27 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
<div className="flex justify-between items-center p-3 bg-green-50 rounded-lg"> <div className="flex justify-between items-center p-3 bg-green-50 rounded-lg">
<span className="text-gray-700">Tahsil Tarihi:</span> <span className="text-gray-700">Tahsil Tarihi:</span>
<span className="font-medium"> <span className="font-medium">
{new Date(item.collectionDate).toLocaleDateString("tr-TR")} {new Date(item.collectionDate).toLocaleDateString('tr-TR')}
</span> </span>
</div> </div>
)} )}
{item.endorsedTo && ( {item.endorsedTo && (
<div className="flex justify-between items-center p-3 bg-purple-50 rounded-lg"> <div className="flex justify-between items-center p-3 bg-purple-50 rounded-lg">
<span className="text-gray-700"> <span className="text-gray-700">Ciro Edildiği Kişi/Kuruluş:</span>
Ciro Edildiği Kişi/Kuruluş:
</span>
<span className="font-medium">{item.endorsedTo}</span> <span className="font-medium">{item.endorsedTo}</span>
</div> </div>
)} )}
{(!isCheck || !(item as FiCheck).bankingDate) && {(!isCheck || !(item as FiCheck).bankingDate) &&
!item.collectionDate && !item.collectionDate &&
!item.endorsedTo && ( !item.endorsedTo && <p className="text-gray-500 italic">Henüz işlem yapılmamış</p>}
<p className="text-gray-500 italic">Henüz işlem yapılmamış</p>
)}
</div> </div>
</div> </div>
{/* Notlar */} {/* Notlar */}
{item.notes && ( {item.notes && (
<div className="bg-gray-50 p-3 rounded-lg"> <div className="bg-gray-50 p-3 rounded-lg">
<h3 className="text-base font-medium text-gray-900 mb-2"> <h3 className="text-base font-medium text-gray-900 mb-2">Notlar</h3>
Notlar <p className="text-sm text-gray-700 whitespace-pre-wrap">{item.notes}</p>
</h3>
<p className="text-sm text-gray-700 whitespace-pre-wrap">
{item.notes}
</p>
</div> </div>
)} )}
</div> </div>
@ -384,7 +315,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
</div> </div>
</div> </div>
</div> </div>
); )
}; }
export default CheckNoteDetails; export default CheckNoteDetails

View file

@ -15,8 +15,7 @@ import {
PromissoryNote, PromissoryNote,
CheckStatusEnum, CheckStatusEnum,
NoteStatusEnum, NoteStatusEnum,
CheckTypeEnum, TypeEnum,
NoteTypeEnum,
FiCurrentAccount, FiCurrentAccount,
} from '../../../types/fi' } from '../../../types/fi'
import DataTable, { Column } from '../../../components/common/DataTable' import DataTable, { Column } from '../../../components/common/DataTable'
@ -71,7 +70,7 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
const [searchTerm, setSearchTerm] = useState('') const [searchTerm, setSearchTerm] = useState('')
const [selectedCheckStatus, setSelectedCheckStatus] = useState<CheckStatusEnum | 'all'>('all') const [selectedCheckStatus, setSelectedCheckStatus] = useState<CheckStatusEnum | 'all'>('all')
const [selectedNoteStatus, setSelectedNoteStatus] = useState<NoteStatusEnum | 'all'>('all') const [selectedNoteStatus, setSelectedNoteStatus] = useState<NoteStatusEnum | 'all'>('all')
const [selectedType, setSelectedType] = useState<CheckTypeEnum | NoteTypeEnum | 'all'>('all') const [selectedType, setSelectedType] = useState<TypeEnum | 'all'>('all')
const [sortBy, setSortBy] = useState<'dueDate' | 'amount' | 'issueDate'>('dueDate') const [sortBy, setSortBy] = useState<'dueDate' | 'amount' | 'issueDate'>('dueDate')
// Dialog states // Dialog states
@ -242,19 +241,19 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
} }
}) })
const getTypeLabel = (type: CheckTypeEnum | NoteTypeEnum) => { const getTypeLabel = (type: TypeEnum) => {
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) { if (type === TypeEnum.Received) {
return 'Alınan' return 'Alınan'
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) { } else if (type === TypeEnum.Issued) {
return 'Verilen' return 'Verilen'
} }
return 'Bilinmeyen' return 'Bilinmeyen'
} }
const getTypeColor = (type: CheckTypeEnum | NoteTypeEnum) => { const getTypeColor = (type: TypeEnum) => {
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) { if (type === TypeEnum.Received) {
return 'bg-green-100 text-green-800' return 'bg-green-100 text-green-800'
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) { } else if (type === TypeEnum.Issued) {
return 'bg-orange-100 text-orange-800' return 'bg-orange-100 text-orange-800'
} }
return 'bg-gray-100 text-gray-800' return 'bg-gray-100 text-gray-800'
@ -593,11 +592,11 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
const totalNoteAmount = promissoryNotes.reduce((sum, note) => sum + note.amount, 0) const totalNoteAmount = promissoryNotes.reduce((sum, note) => sum + note.amount, 0)
const receivedCheckAmount = checks const receivedCheckAmount = checks
.filter((c) => c.type === CheckTypeEnum.Received && c.status !== CheckStatusEnum.Collected) .filter((c) => c.type === TypeEnum.Received && c.status !== CheckStatusEnum.Collected)
.reduce((sum, c) => sum + c.amount, 0) .reduce((sum, c) => sum + c.amount, 0)
const receivedNoteAmount = promissoryNotes const receivedNoteAmount = promissoryNotes
.filter((n) => n.type === NoteTypeEnum.Received && n.status !== NoteStatusEnum.Collected) .filter((n) => n.type === TypeEnum.Received && n.status !== NoteStatusEnum.Collected)
.reduce((sum, n) => sum + n.amount, 0) .reduce((sum, n) => sum + n.amount, 0)
// Due items // Due items
@ -756,9 +755,7 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
<select <select
value={selectedType} value={selectedType}
onChange={(e) => onChange={(e) => setSelectedType(e.target.value as TypeEnum | 'all')}
setSelectedType(e.target.value as CheckTypeEnum | NoteTypeEnum | 'all')
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Türler</option> <option value="all">Tüm Türler</option>

View file

@ -1,24 +1,15 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { import { FaTimes, FaUser, FaBuilding, FaCreditCard, FaPhoneAlt } from 'react-icons/fa'
FaTimes, import { FiCurrentAccount, AccountTypeEnum, RiskGroupEnum } from '../../../types/fi'
FaUser, import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
FaBuilding, import { getAccountTypeText, getRiskGroupText } from '../../../utils/erp'
FaCreditCard, import { mockCurrencies } from '@/mocks/mockCurrencies'
FaPhoneAlt,
} from "react-icons/fa";
import {
FiCurrentAccount,
AccountTypeEnum,
RiskGroupEnum,
} from "../../../types/fi";
import { mockBusinessParties } from "../../../mocks/mockBusinessParties";
import { getAccountTypeText, getRiskGroupText } from "../../../utils/erp";
interface CurrentAccountFormProps { interface CurrentAccountFormProps {
account?: FiCurrentAccount; account?: FiCurrentAccount
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: (account: Partial<FiCurrentAccount>) => void; onSave: (account: Partial<FiCurrentAccount>) => void
} }
const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
@ -29,26 +20,26 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
}) => { }) => {
const [formData, setFormData] = useState< const [formData, setFormData] = useState<
Partial<FiCurrentAccount> & { Partial<FiCurrentAccount> & {
id?: string; id?: string
} }
>({ >({
accountCode: "", accountCode: '',
businessPartyId: "", businessPartyId: '',
type: AccountTypeEnum.Customer, type: AccountTypeEnum.Customer,
contactPerson: "", contactPerson: '',
phone: "", phone: '',
email: "", email: '',
address: "", address: '',
taxNumber: "", taxNumber: '',
taxOffice: "", taxOffice: '',
creditLimit: 0, creditLimit: 0,
currency: "TRY", currency: 'TRY',
riskGroup: RiskGroupEnum.Low, riskGroup: RiskGroupEnum.Low,
paymentTerm: 30, paymentTerm: 30,
isActive: true, isActive: true,
}); })
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({})
useEffect(() => { useEffect(() => {
if (account) { if (account) {
@ -56,100 +47,95 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
...account, ...account,
creditLimit: account.creditLimit || 0, creditLimit: account.creditLimit || 0,
paymentTerm: account.paymentTerm || 30, paymentTerm: account.paymentTerm || 30,
}); })
} else { } else {
setFormData({ setFormData({
accountCode: "", accountCode: '',
businessPartyId: "", businessPartyId: '',
type: AccountTypeEnum.Customer, type: AccountTypeEnum.Customer,
contactPerson: "", contactPerson: '',
phone: "", phone: '',
email: "", email: '',
address: "", address: '',
taxNumber: "", taxNumber: '',
taxOffice: "", taxOffice: '',
creditLimit: 0, creditLimit: 0,
currency: "TRY", currency: 'TRY',
riskGroup: RiskGroupEnum.Low, riskGroup: RiskGroupEnum.Low,
paymentTerm: 30, paymentTerm: 30,
isActive: true, isActive: true,
}); })
} }
setErrors({}); setErrors({})
}, [account, isOpen]); }, [account, isOpen])
const handleInputChange = ( const handleInputChange = (
e: React.ChangeEvent< e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
>
) => { ) => {
const { name, value, type } = e.target; const { name, value, type } = e.target
let parsedValue: string | number | boolean = value; let parsedValue: string | number | boolean = value
if (type === "number") { if (type === 'number') {
parsedValue = value === "" ? 0 : parseFloat(value); parsedValue = value === '' ? 0 : parseFloat(value)
} else if (type === "checkbox") { } else if (type === 'checkbox') {
parsedValue = (e.target as HTMLInputElement).checked; parsedValue = (e.target as HTMLInputElement).checked
} }
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: parsedValue, [name]: parsedValue,
})); }))
// Clear error when user starts typing // Clear error when user starts typing
if (errors[name]) { if (errors[name]) {
setErrors((prev) => ({ setErrors((prev) => ({
...prev, ...prev,
[name]: "", [name]: '',
})); }))
} }
}; }
const validateForm = () => { const validateForm = () => {
const newErrors: Record<string, string> = {}; const newErrors: Record<string, string> = {}
if (!formData.accountCode?.trim()) { if (!formData.accountCode?.trim()) {
newErrors.accountCode = "Hesap kodu zorunludur"; newErrors.accountCode = 'Hesap kodu zorunludur'
} }
if (!formData.businessPartyId?.trim()) { if (!formData.businessPartyId?.trim()) {
newErrors.businessPartyId = "Ünvan zorunludur"; newErrors.businessPartyId = 'Ünvan zorunludur'
} }
if (formData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { if (formData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
newErrors.email = "Geçerli bir e-posta adresi giriniz"; newErrors.email = 'Geçerli bir e-posta adresi giriniz'
} }
if (formData.creditLimit && formData.creditLimit < 0) { if (formData.creditLimit && formData.creditLimit < 0) {
newErrors.creditLimit = "Kredi limiti negatif olamaz"; newErrors.creditLimit = 'Kredi limiti negatif olamaz'
} }
if (formData.paymentTerm && formData.paymentTerm < 0) { if (formData.paymentTerm && formData.paymentTerm < 0) {
newErrors.paymentTerm = "Ödeme vadesi negatif olamaz"; newErrors.paymentTerm = 'Ödeme vadesi negatif olamaz'
} }
setErrors(newErrors); setErrors(newErrors)
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (validateForm()) { if (validateForm()) {
onSave(formData); onSave(formData)
onClose(); onClose()
} }
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg w-full max-w-3xl max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg w-full max-w-3xl max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{account ? "Cari Hesap Düzenle" : "Yeni Cari Hesap"} {account ? 'Cari Hesap Düzenle' : 'Yeni Cari Hesap'}
</h2> </h2>
<button <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
onClick={onClose}
className="text-gray-400 hover:text-gray-600"
>
<FaTimes className="w-5 h-5" /> <FaTimes className="w-5 h-5" />
</button> </button>
</div> </div>
@ -164,34 +150,28 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
</h3> </h3>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Hesap Kodu *</label>
Hesap Kodu *
</label>
<input <input
type="text" type="text"
name="accountCode" name="accountCode"
value={formData.accountCode || ""} value={formData.accountCode || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.accountCode ? "border-red-500" : "border-gray-300" errors.accountCode ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="CA001" placeholder="CA001"
/> />
{errors.accountCode && ( {errors.accountCode && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.accountCode}</p>
{errors.accountCode}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Ünvan *</label>
Ünvan *
</label>
<select <select
name="businessPartyId" name="businessPartyId"
value={formData.businessPartyId || ""} value={formData.businessPartyId || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="mt-1 block w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
required required
@ -203,15 +183,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
</option> </option>
))} ))}
</select> </select>
{errors.title && ( {errors.title && <p className="text-red-500 text-xs mt-1">{errors.title}</p>}
<p className="text-red-500 text-xs mt-1">{errors.title}</p>
)}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Hesap Türü</label>
Hesap Türü
</label>
<select <select
name="type" name="type"
value={formData.type} value={formData.type}
@ -227,13 +203,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Yetkili Kişi</label>
Yetkili Kişi
</label>
<input <input
type="text" type="text"
name="contactPerson" name="contactPerson"
value={formData.contactPerson || ""} value={formData.contactPerson || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Yetkili kişi adı" placeholder="Yetkili kişi adı"
@ -249,13 +223,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
</h3> </h3>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
Telefon
</label>
<input <input
type="text" type="text"
name="phone" name="phone"
value={formData.phone || ""} value={formData.phone || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="+90 212 555 1234" placeholder="+90 212 555 1234"
@ -263,31 +235,25 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
E-posta
</label>
<input <input
type="email" type="email"
name="email" name="email"
value={formData.email || ""} value={formData.email || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.email ? "border-red-500" : "border-gray-300" errors.email ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="info@company.com" placeholder="info@company.com"
/> />
{errors.email && ( {errors.email && <p className="text-red-500 text-xs mt-1">{errors.email}</p>}
<p className="text-red-500 text-xs mt-1">{errors.email}</p>
)}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Adres</label>
Adres
</label>
<textarea <textarea
name="address" name="address"
value={formData.address || ""} value={formData.address || ''}
onChange={handleInputChange} onChange={handleInputChange}
rows={3} rows={3}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
@ -303,7 +269,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
<input <input
type="text" type="text"
name="taxNumber" name="taxNumber"
value={formData.taxNumber || ""} value={formData.taxNumber || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="1234567890" placeholder="1234567890"
@ -317,7 +283,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
<input <input
type="text" type="text"
name="taxOffice" name="taxOffice"
value={formData.taxOffice || ""} value={formData.taxOffice || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Beylikdüzü V.D." placeholder="Beylikdüzü V.D."
@ -346,14 +312,12 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
min="0" min="0"
step="0.01" step="0.01"
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.creditLimit ? "border-red-500" : "border-gray-300" errors.creditLimit ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="0.00" placeholder="0.00"
/> />
{errors.creditLimit && ( {errors.creditLimit && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.creditLimit}</p>
{errors.creditLimit}
</p>
)} )}
</div> </div>
@ -367,19 +331,18 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY - Türk Lirası</option> {mockCurrencies.map((currency) => (
<option value="USD">USD - Amerikan Doları</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR - Euro</option> {currency.value} - {currency.label}
<option value="GBP">GBP - İngiliz Sterlini</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Risk Grubu</label>
Risk Grubu
</label>
<select <select
name="riskGroup" name="riskGroup"
value={formData.riskGroup} value={formData.riskGroup}
@ -405,14 +368,12 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
min="0" min="0"
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.paymentTerm ? "border-red-500" : "border-gray-300" errors.paymentTerm ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="30" placeholder="30"
/> />
{errors.paymentTerm && ( {errors.paymentTerm && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.paymentTerm}</p>
{errors.paymentTerm}
</p>
)} )}
</div> </div>
</div> </div>
@ -433,9 +394,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/> />
<label className="ml-2 block text-sm text-gray-700"> <label className="ml-2 block text-sm text-gray-700">Aktif hesap</label>
Aktif hesap
</label>
</div> </div>
</div> </div>
</div> </div>
@ -453,13 +412,13 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
type="submit" type="submit"
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors" className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
> >
{account ? "Güncelle" : "Ekle"} {account ? 'Güncelle' : 'Ekle'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default CurrentAccountForm; export default CurrentAccountForm

View file

@ -1,18 +1,15 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaTimes, FaFileInvoice, FaMoneyBill } from "react-icons/fa"; import { FaTimes, FaFileInvoice, FaMoneyBill } from 'react-icons/fa'
import { import { FiCurrentAccountMovement, FiDocumentTypeEnum, FiCurrentAccount } from '../../../types/fi'
FiCurrentAccountMovement, import { getFiDocumentTypeText } from '../../../utils/erp'
FiDocumentTypeEnum, import { mockCurrencies } from '@/mocks/mockCurrencies'
FiCurrentAccount,
} from "../../../types/fi";
import { getFiDocumentTypeText } from "../../../utils/erp";
interface CurrentAccountMovementFormProps { interface CurrentAccountMovementFormProps {
movement?: FiCurrentAccountMovement; movement?: FiCurrentAccountMovement
accounts: FiCurrentAccount[]; accounts: FiCurrentAccount[]
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: (movement: Partial<FiCurrentAccountMovement>) => void; onSave: (movement: Partial<FiCurrentAccountMovement>) => void
} }
const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
@ -24,22 +21,22 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
}) => { }) => {
const [formData, setFormData] = useState< const [formData, setFormData] = useState<
Partial<FiCurrentAccountMovement> & { Partial<FiCurrentAccountMovement> & {
id?: string; id?: string
} }
>({ >({
accountId: "", accountId: '',
transactionDate: new Date(), transactionDate: new Date(),
description: "", description: '',
referenceNumber: "", referenceNumber: '',
documentType: FiDocumentTypeEnum.Invoice, documentType: FiDocumentTypeEnum.Invoice,
documentNumber: "", documentNumber: '',
debitAmount: 0, debitAmount: 0,
creditAmount: 0, creditAmount: 0,
balance: 0, balance: 0,
currency: "TRY", currency: 'TRY',
}); })
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({})
useEffect(() => { useEffect(() => {
if (movement) { if (movement) {
@ -48,111 +45,100 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
debitAmount: movement.debitAmount || 0, debitAmount: movement.debitAmount || 0,
creditAmount: movement.creditAmount || 0, creditAmount: movement.creditAmount || 0,
balance: movement.balance || 0, balance: movement.balance || 0,
}); })
} else { } else {
setFormData({ setFormData({
accountId: "", accountId: '',
transactionDate: new Date(), transactionDate: new Date(),
description: "", description: '',
referenceNumber: "", referenceNumber: '',
documentType: FiDocumentTypeEnum.Invoice, documentType: FiDocumentTypeEnum.Invoice,
documentNumber: "", documentNumber: '',
debitAmount: 0, debitAmount: 0,
creditAmount: 0, creditAmount: 0,
balance: 0, balance: 0,
currency: "TRY", currency: 'TRY',
}); })
} }
setErrors({}); setErrors({})
}, [movement, isOpen]); }, [movement, isOpen])
const handleInputChange = ( const handleInputChange = (
e: React.ChangeEvent< e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
>
) => { ) => {
const { name, value, type } = e.target; const { name, value, type } = e.target
let parsedValue: string | number | Date = value; let parsedValue: string | number | Date = value
if (type === "number") { if (type === 'number') {
parsedValue = value === "" ? 0 : parseFloat(value); parsedValue = value === '' ? 0 : parseFloat(value)
} else if (type === "date") { } else if (type === 'date') {
parsedValue = new Date(value); parsedValue = new Date(value)
} }
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: parsedValue, [name]: parsedValue,
})); }))
// Clear error when user starts typing // Clear error when user starts typing
if (errors[name]) { if (errors[name]) {
setErrors((prev) => ({ setErrors((prev) => ({
...prev, ...prev,
[name]: "", [name]: '',
})); }))
} }
}; }
const validateForm = () => { const validateForm = () => {
const newErrors: Record<string, string> = {}; const newErrors: Record<string, string> = {}
if (!formData.accountId) { if (!formData.accountId) {
newErrors.accountId = "Cari hesap seçimi zorunludur"; newErrors.accountId = 'Cari hesap seçimi zorunludur'
} }
if (!formData.description?.trim()) { if (!formData.description?.trim()) {
newErrors.description = "Açıklama zorunludur"; newErrors.description = 'Açıklama zorunludur'
} }
if (!formData.transactionDate) { if (!formData.transactionDate) {
newErrors.transactionDate = "İşlem tarihi zorunludur"; newErrors.transactionDate = 'İşlem tarihi zorunludur'
} }
if ( if ((formData.debitAmount || 0) === 0 && (formData.creditAmount || 0) === 0) {
(formData.debitAmount || 0) === 0 && newErrors.amount = 'Borç veya alacak tutarından biri girilmelidir'
(formData.creditAmount || 0) === 0
) {
newErrors.amount = "Borç veya alacak tutarından biri girilmelidir";
} }
if ((formData.debitAmount || 0) > 0 && (formData.creditAmount || 0) > 0) { if ((formData.debitAmount || 0) > 0 && (formData.creditAmount || 0) > 0) {
newErrors.amount = "Borç ve alacak tutarı aynı anda girilemez"; newErrors.amount = 'Borç ve alacak tutarı aynı anda girilemez'
} }
setErrors(newErrors); setErrors(newErrors)
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (validateForm()) { if (validateForm()) {
// Calculate balance based on debit/credit amounts // Calculate balance based on debit/credit amounts
const balance = const balance = (formData.debitAmount || 0) - (formData.creditAmount || 0)
(formData.debitAmount || 0) - (formData.creditAmount || 0);
const movementData = { const movementData = {
...formData, ...formData,
balance, balance,
creationTime: movement?.creationTime || new Date(), creationTime: movement?.creationTime || new Date(),
}; }
onSave(movementData); onSave(movementData)
onClose(); onClose()
} }
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{movement {movement ? 'Cari Hesap Hareketi Düzenle' : 'Yeni Cari Hesap Hareketi'}
? "Cari Hesap Hareketi Düzenle"
: "Yeni Cari Hesap Hareketi"}
</h2> </h2>
<button <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
onClick={onClose}
className="text-gray-400 hover:text-gray-600"
>
<FaTimes className="w-5 h-5" /> <FaTimes className="w-5 h-5" />
</button> </button>
</div> </div>
@ -167,15 +153,13 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
</h3> </h3>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap *</label>
Cari Hesap *
</label>
<select <select
name="accountId" name="accountId"
value={formData.accountId || ""} value={formData.accountId || ''}
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.accountId ? "border-red-500" : "border-gray-300" errors.accountId ? 'border-red-500' : 'border-gray-300'
}`} }`}
> >
<option value="">Cari hesap seçiniz</option> <option value="">Cari hesap seçiniz</option>
@ -186,9 +170,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
))} ))}
</select> </select>
{errors.accountId && ( {errors.accountId && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.accountId}</p>
{errors.accountId}
</p>
)} )}
</div> </div>
@ -201,29 +183,21 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
name="transactionDate" name="transactionDate"
value={ value={
formData.transactionDate formData.transactionDate
? new Date(formData.transactionDate) ? new Date(formData.transactionDate).toISOString().split('T')[0]
.toISOString() : ''
.split("T")[0]
: ""
} }
onChange={handleInputChange} onChange={handleInputChange}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.transactionDate errors.transactionDate ? 'border-red-500' : 'border-gray-300'
? "border-red-500"
: "border-gray-300"
}`} }`}
/> />
{errors.transactionDate && ( {errors.transactionDate && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.transactionDate}</p>
{errors.transactionDate}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Belge Türü</label>
Belge Türü
</label>
<select <select
name="documentType" name="documentType"
value={formData.documentType} value={formData.documentType}
@ -246,7 +220,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
<input <input
type="text" type="text"
name="referenceNumber" name="referenceNumber"
value={formData.referenceNumber || ""} value={formData.referenceNumber || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="REF001" placeholder="REF001"
@ -254,13 +228,11 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Belge No</label>
Belge No
</label>
<input <input
type="text" type="text"
name="documentNumber" name="documentNumber"
value={formData.documentNumber || ""} value={formData.documentNumber || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="DOC001" placeholder="DOC001"
@ -277,9 +249,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
</h3> </h3>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Borç Tutarı</label>
Borç Tutarı
</label>
<input <input
type="number" type="number"
name="debitAmount" name="debitAmount"
@ -309,19 +279,18 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
Para Birimi
</label>
<select <select
name="currency" name="currency"
value={formData.currency} value={formData.currency}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY - Türk Lirası</option> {mockCurrencies.map((currency) => (
<option value="USD">USD - Amerikan Doları</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR - Euro</option> {currency.value} - {currency.label}
<option value="GBP">GBP - İngiliz Sterlini</option> </option>
))}
</select> </select>
</div> </div>
@ -333,37 +302,34 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
<div className="p-2 bg-blue-50 border border-blue-200 rounded-md"> <div className="p-2 bg-blue-50 border border-blue-200 rounded-md">
<p className="text-blue-800 text-sm"> <p className="text-blue-800 text-sm">
<strong>Hesaplanan Bakiye:</strong>{" "} <strong>Hesaplanan Bakiye:</strong>{' '}
{( {((formData.debitAmount || 0) - (formData.creditAmount || 0)).toLocaleString(
(formData.debitAmount || 0) - (formData.creditAmount || 0) 'tr-TR',
).toLocaleString("tr-TR", { {
style: "currency", style: 'currency',
currency: formData.currency || "TRY", currency: formData.currency || 'TRY',
minimumFractionDigits: 2, minimumFractionDigits: 2,
})} },
)}
</p> </p>
</div> </div>
</div> </div>
{/* Açıklama */} {/* Açıklama */}
<div className="md:col-span-2"> <div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">ıklama *</label>
ıklama *
</label>
<textarea <textarea
name="description" name="description"
value={formData.description || ""} value={formData.description || ''}
onChange={handleInputChange} onChange={handleInputChange}
rows={3} rows={3}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.description ? "border-red-500" : "border-gray-300" errors.description ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Hareket açıklaması" placeholder="Hareket açıklaması"
/> />
{errors.description && ( {errors.description && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.description}</p>
{errors.description}
</p>
)} )}
</div> </div>
</div> </div>
@ -381,13 +347,13 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
type="submit" type="submit"
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors" className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
> >
{movement ? "Güncelle" : "Ekle"} {movement ? 'Güncelle' : 'Ekle'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default CurrentAccountMovementForm; export default CurrentAccountMovementForm

View file

@ -1,31 +1,27 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from "react-icons/fa"; import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from 'react-icons/fa'
import { import {
FiInvoice, FiInvoice,
FiInvoiceItem, FiInvoiceItem,
InvoiceTypeEnum, InvoiceTypeEnum,
InvoiceStatusEnum, InvoiceStatusEnum,
PaymentStatusEnum, PaymentStatusEnum,
} from "../../../types/fi"; } from '../../../types/fi'
import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts"; import { mockCurrentAccounts } from '../../../mocks/mockCurrentAccounts'
import { getInvoiceTypeText } from '@/utils/erp'
interface InvoiceFormProps { interface InvoiceFormProps {
invoice?: FiInvoice; invoice?: FiInvoice
onSave: (invoice: Partial<FiInvoice>) => void; onSave: (invoice: Partial<FiInvoice>) => void
onCancel: () => void; onCancel: () => void
isVisible: boolean; isVisible: boolean
} }
const InvoiceForm: React.FC<InvoiceFormProps> = ({ const InvoiceForm: React.FC<InvoiceFormProps> = ({ invoice, onSave, onCancel, isVisible }) => {
invoice,
onSave,
onCancel,
isVisible,
}) => {
const [formData, setFormData] = useState<Partial<FiInvoice>>({ const [formData, setFormData] = useState<Partial<FiInvoice>>({
invoiceNumber: "", invoiceNumber: '',
invoiceType: InvoiceTypeEnum.Sales, invoiceType: InvoiceTypeEnum.Sales,
currentAccountId: "", currentAccountId: '',
invoiceDate: new Date(), invoiceDate: new Date(),
dueDate: new Date(), dueDate: new Date(),
deliveryDate: new Date(), deliveryDate: new Date(),
@ -35,22 +31,22 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
totalAmount: 0, totalAmount: 0,
paidAmount: 0, paidAmount: 0,
remainingAmount: 0, remainingAmount: 0,
currency: "TRY", currency: 'TRY',
status: InvoiceStatusEnum.Draft, status: InvoiceStatusEnum.Draft,
paymentStatus: PaymentStatusEnum.Unpaid, paymentStatus: PaymentStatusEnum.Unpaid,
items: [], items: [],
waybillNumber: "", waybillNumber: '',
notes: "", notes: '',
}); })
const [newItem, setNewItem] = useState<Partial<FiInvoiceItem>>({ const [newItem, setNewItem] = useState<Partial<FiInvoiceItem>>({
description: "", description: '',
quantity: 1, quantity: 1,
unitPrice: 0, unitPrice: 0,
taxRate: 18, taxRate: 18,
discountRate: 0, discountRate: 0,
unit: "Adet", unit: 'Adet',
}); })
useEffect(() => { useEffect(() => {
if (invoice) { if (invoice) {
@ -58,18 +54,17 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
...invoice, ...invoice,
invoiceDate: new Date(invoice.invoiceDate), invoiceDate: new Date(invoice.invoiceDate),
dueDate: new Date(invoice.dueDate), dueDate: new Date(invoice.dueDate),
deliveryDate: invoice.deliveryDate deliveryDate: invoice.deliveryDate ? new Date(invoice.deliveryDate) : new Date(),
? new Date(invoice.deliveryDate) })
: new Date(),
});
} else { } else {
// Generate new invoice number // Generate new invoice number
const now = new Date(); const now = new Date()
const year = now.getFullYear(); const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, "0"); const month = String(now.getMonth() + 1).padStart(2, '0')
const invoiceNumber = `FT${year}${month}${String( const invoiceNumber = `FT${year}${month}${String(Math.floor(Math.random() * 10000)).padStart(
Math.floor(Math.random() * 10000) 4,
).padStart(4, "0")}`; '0',
)}`
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
@ -77,58 +72,50 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
invoiceDate: now, invoiceDate: now,
dueDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), // 30 days dueDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), // 30 days
deliveryDate: now, deliveryDate: now,
})); }))
} }
}, [invoice]); }, [invoice])
const calculateItemTotal = (item: Partial<FiInvoiceItem>) => { const calculateItemTotal = (item: Partial<FiInvoiceItem>) => {
const subtotal = (item.quantity || 0) * (item.unitPrice || 0); const subtotal = (item.quantity || 0) * (item.unitPrice || 0)
const discountAmount = subtotal * ((item.discountRate || 0) / 100); const discountAmount = subtotal * ((item.discountRate || 0) / 100)
const taxableAmount = subtotal - discountAmount; const taxableAmount = subtotal - discountAmount
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100); const taxAmount = taxableAmount * ((item.taxRate || 0) / 100)
return taxableAmount + taxAmount; return taxableAmount + taxAmount
}; }
const calculateInvoiceTotals = (items: FiInvoiceItem[]) => { const calculateInvoiceTotals = (items: FiInvoiceItem[]) => {
const subtotal = items.reduce( const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0)
(sum, item) => sum + item.quantity * item.unitPrice, const discountAmount = items.reduce((sum, item) => sum + item.discountAmount, 0)
0 const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0)
); const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0)
const discountAmount = items.reduce(
(sum, item) => sum + item.discountAmount,
0
);
const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0);
const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0);
return { return {
subtotal, subtotal,
discountAmount, discountAmount,
taxAmount, taxAmount,
totalAmount, totalAmount,
}; }
}; }
const handleAddItem = () => { const handleAddItem = () => {
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) { if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
alert("Lütfen ürün bilgilerini doldurun"); alert('Lütfen ürün bilgilerini doldurun')
return; return
} }
const item: FiInvoiceItem = { const item: FiInvoiceItem = {
id: Date.now().toString(), id: Date.now().toString(),
invoiceId: formData.id || "", invoiceId: formData.id || '',
description: newItem.description!, description: newItem.description!,
quantity: newItem.quantity!, quantity: newItem.quantity!,
unitPrice: newItem.unitPrice!, unitPrice: newItem.unitPrice!,
unit: newItem.unit || "Adet", unit: newItem.unit || 'Adet',
taxRate: newItem.taxRate || 18, taxRate: newItem.taxRate || 18,
discountRate: newItem.discountRate || 0, discountRate: newItem.discountRate || 0,
lineTotal: calculateItemTotal(newItem), lineTotal: calculateItemTotal(newItem),
discountAmount: discountAmount:
(newItem.quantity || 0) * (newItem.quantity || 0) * (newItem.unitPrice || 0) * ((newItem.discountRate || 0) / 100),
(newItem.unitPrice || 0) *
((newItem.discountRate || 0) / 100),
taxAmount: taxAmount:
((newItem.quantity || 0) * (newItem.unitPrice || 0) - ((newItem.quantity || 0) * (newItem.unitPrice || 0) -
(newItem.quantity || 0) * (newItem.quantity || 0) *
@ -136,50 +123,49 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
((newItem.discountRate || 0) / 100)) * ((newItem.discountRate || 0) / 100)) *
((newItem.taxRate || 0) / 100), ((newItem.taxRate || 0) / 100),
netAmount: calculateItemTotal(newItem), netAmount: calculateItemTotal(newItem),
}; }
const updatedItems = [...(formData.items || []), item]; const updatedItems = [...(formData.items || []), item]
const totals = calculateInvoiceTotals(updatedItems); const totals = calculateInvoiceTotals(updatedItems)
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
items: updatedItems, items: updatedItems,
...totals, ...totals,
remainingAmount: totals.totalAmount - (prev.paidAmount || 0), remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
})); }))
setNewItem({ setNewItem({
description: "", description: '',
quantity: 1, quantity: 1,
unitPrice: 0, unitPrice: 0,
taxRate: 18, taxRate: 18,
discountRate: 0, discountRate: 0,
unit: "Adet", unit: 'Adet',
}); })
}; }
const handleRemoveItem = (itemId: string) => { const handleRemoveItem = (itemId: string) => {
const updatedItems = const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []
formData.items?.filter((item) => item.id !== itemId) || []; const totals = calculateInvoiceTotals(updatedItems)
const totals = calculateInvoiceTotals(updatedItems);
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
items: updatedItems, items: updatedItems,
...totals, ...totals,
remainingAmount: totals.totalAmount - (prev.paidAmount || 0), remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
})); }))
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (!formData.currentAccountId) { if (!formData.currentAccountId) {
alert("Lütfen cari hesap seçin"); alert('Lütfen cari hesap seçin')
return; return
} }
if (!formData.items?.length) { if (!formData.items?.length) {
alert("Lütfen en az bir ürün ekleyin"); alert('Lütfen en az bir ürün ekleyin')
return; return
} }
onSave({ onSave({
@ -187,18 +173,18 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
id: invoice?.id || Date.now().toString(), id: invoice?.id || Date.now().toString(),
creationTime: invoice?.creationTime || new Date(), creationTime: invoice?.creationTime || new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}); })
}; }
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return amount.toLocaleString("tr-TR", { return amount.toLocaleString('tr-TR', {
style: "currency", style: 'currency',
currency: "TRY", currency: 'TRY',
minimumFractionDigits: 2, minimumFractionDigits: 2,
}); })
}; }
if (!isVisible) return null; if (!isVisible) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"> <div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
@ -208,7 +194,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
<div className="flex items-center gap-2.5"> <div className="flex items-center gap-2.5">
<FaFileAlt className="w-5 h-5 text-blue-600" /> <FaFileAlt className="w-5 h-5 text-blue-600" />
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{invoice ? "Fatura Düzenle" : "Yeni Fatura"} {invoice ? 'Fatura Düzenle' : 'Yeni Fatura'}
</h2> </h2>
</div> </div>
<button <button
@ -224,24 +210,18 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
{/* Basic Information */} {/* Basic Information */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Fatura No</label>
Fatura No
</label>
<input <input
type="text" type="text"
value={formData.invoiceNumber} value={formData.invoiceNumber}
onChange={(e) => onChange={(e) => setFormData({ ...formData, invoiceNumber: e.target.value })}
setFormData({ ...formData, invoiceNumber: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required required
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Fatura Türü</label>
Fatura Türü
</label>
<select <select
value={formData.invoiceType} value={formData.invoiceType}
onChange={(e) => onChange={(e) =>
@ -252,36 +232,29 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={InvoiceTypeEnum.Sales}>Satış</option> {Object.values(InvoiceTypeEnum).map((type) => (
<option value={InvoiceTypeEnum.Purchase}>Alış</option> <option key={type} value={type}>
<option value={InvoiceTypeEnum.Return}>İade</option> {getInvoiceTypeText(type)}
<option value={InvoiceTypeEnum.Proforma}>Proforma</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye No</label>
İrsaliye No
</label>
<input <input
type="text" type="text"
value={formData.waybillNumber || ""} value={formData.waybillNumber || ''}
onChange={(e) => onChange={(e) => setFormData({ ...formData, waybillNumber: e.target.value })}
setFormData({ ...formData, waybillNumber: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Cari Hesap</label>
Cari Hesap
</label>
<select <select
value={formData.currentAccountId} value={formData.currentAccountId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, currentAccountId: e.target.value })}
setFormData({ ...formData, currentAccountId: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required required
> >
@ -295,12 +268,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Fatura Tarihi</label>
Fatura Tarihi
</label>
<input <input
type="date" type="date"
value={formData.invoiceDate?.toISOString().split("T")[0]} value={formData.invoiceDate?.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -313,12 +284,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Vade Tarihi</label>
Vade Tarihi
</label>
<input <input
type="date" type="date"
value={formData.dueDate?.toISOString().split("T")[0]} value={formData.dueDate?.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -333,9 +302,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
{/* Invoice Items */} {/* Invoice Items */}
<div className="mb-6"> <div className="mb-6">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">Fatura Kalemleri</h3>
Fatura Kalemleri
</h3>
{/* Add New Item */} {/* Add New Item */}
<div className="bg-gray-50 p-3 rounded-lg mb-3"> <div className="bg-gray-50 p-3 rounded-lg mb-3">
@ -346,21 +313,17 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
</label> </label>
<input <input
type="text" type="text"
value={newItem.description || ""} value={newItem.description || ''}
onChange={(e) => onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
setNewItem({ ...newItem, description: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Ürün/Hizmet açıklaması" placeholder="Ürün/Hizmet açıklaması"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Miktar</label>
Miktar
</label>
<input <input
type="number" type="number"
value={newItem.quantity || ""} value={newItem.quantity || ''}
onChange={(e) => onChange={(e) =>
setNewItem({ setNewItem({
...newItem, ...newItem,
@ -378,7 +341,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
</label> </label>
<input <input
type="number" type="number"
value={newItem.unitPrice || ""} value={newItem.unitPrice || ''}
onChange={(e) => onChange={(e) =>
setNewItem({ setNewItem({
...newItem, ...newItem,
@ -391,11 +354,9 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">KDV (%)</label>
KDV (%)
</label>
<select <select
value={newItem.taxRate || 18} value={newItem.taxRate || 20}
onChange={(e) => onChange={(e) =>
setNewItem({ setNewItem({
...newItem, ...newItem,
@ -408,6 +369,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
<option value={1}>1%</option> <option value={1}>1%</option>
<option value={8}>8%</option> <option value={8}>8%</option>
<option value={18}>18%</option> <option value={18}>18%</option>
<option value={20}>20%</option>
</select> </select>
</div> </div>
<div className="flex items-end"> <div className="flex items-end">
@ -452,18 +414,14 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
<tbody className="divide-y divide-gray-200"> <tbody className="divide-y divide-gray-200">
{formData.items.map((item) => ( {formData.items.map((item) => (
<tr key={item.id} className="text-sm"> <tr key={item.id} className="text-sm">
<td className="px-3 py-2 text-gray-900"> <td className="px-3 py-2 text-gray-900">{item.description}</td>
{item.description}
</td>
<td className="px-3 py-2 text-gray-900 text-right"> <td className="px-3 py-2 text-gray-900 text-right">
{item.quantity.toLocaleString("tr-TR")} {item.quantity.toLocaleString('tr-TR')}
</td> </td>
<td className="px-3 py-2 text-gray-900 text-right"> <td className="px-3 py-2 text-gray-900 text-right">
{formatCurrency(item.unitPrice)} {formatCurrency(item.unitPrice)}
</td> </td>
<td className="px-3 py-2 text-gray-900 text-right"> <td className="px-3 py-2 text-gray-900 text-right">%{item.taxRate}</td>
%{item.taxRate}
</td>
<td className="px-3 py-2 text-gray-900 text-right font-medium"> <td className="px-3 py-2 text-gray-900 text-right font-medium">
{formatCurrency(item.lineTotal)} {formatCurrency(item.lineTotal)}
</td> </td>
@ -488,14 +446,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
<div className="bg-gray-50 p-4 rounded-lg mb-4"> <div className="bg-gray-50 p-4 rounded-lg mb-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Notlar</label>
Notlar
</label>
<textarea <textarea
value={formData.notes || ""} value={formData.notes || ''}
onChange={(e) => onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
setFormData({ ...formData, notes: e.target.value })
}
rows={4} rows={4}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Fatura ile ilgili notlar..." placeholder="Fatura ile ilgili notlar..."
@ -504,9 +458,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
<div className="space-y-2 text-sm"> <div className="space-y-2 text-sm">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm text-gray-600">Ara Toplam:</span> <span className="text-sm text-gray-600">Ara Toplam:</span>
<span className="font-medium"> <span className="font-medium">{formatCurrency(formData.subtotal || 0)}</span>
{formatCurrency(formData.subtotal || 0)}
</span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm text-gray-600">İndirim:</span> <span className="text-sm text-gray-600">İndirim:</span>
@ -516,15 +468,11 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm text-gray-600">KDV:</span> <span className="text-sm text-gray-600">KDV:</span>
<span className="font-medium"> <span className="font-medium">{formatCurrency(formData.taxAmount || 0)}</span>
{formatCurrency(formData.taxAmount || 0)}
</span>
</div> </div>
<div className="border-t pt-3"> <div className="border-t pt-3">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-base font-semibold text-gray-900"> <span className="text-base font-semibold text-gray-900">Genel Toplam:</span>
Genel Toplam:
</span>
<span className="text-base font-bold text-blue-600"> <span className="text-base font-bold text-blue-600">
{formatCurrency(formData.totalAmount || 0)} {formatCurrency(formData.totalAmount || 0)}
</span> </span>
@ -548,13 +496,13 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2" className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{invoice ? "Güncelle" : "Kaydet"} {invoice ? 'Güncelle' : 'Kaydet'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default InvoiceForm; export default InvoiceForm

View file

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import { import {
FaPlus, FaPlus,
FaSearch, FaSearch,
@ -8,15 +8,10 @@ import {
FaFileAlt, FaFileAlt,
FaEdit, FaEdit,
FaSave, FaSave,
} from "react-icons/fa"; } from 'react-icons/fa'
import { import { FiInvoice, InvoiceTypeEnum, InvoiceStatusEnum, PaymentStatusEnum } from '../../../types/fi'
FiInvoice, import DataTable, { Column } from '../../../components/common/DataTable'
InvoiceTypeEnum, import Widget from '../../../components/common/Widget'
InvoiceStatusEnum,
PaymentStatusEnum,
} from "../../../types/fi";
import DataTable, { Column } from "../../../components/common/DataTable";
import Widget from "../../../components/common/Widget";
import { import {
getInvoiceTypeColor, getInvoiceTypeColor,
getInvoiceTypeText, getInvoiceTypeText,
@ -24,15 +19,15 @@ import {
getInvoiceStatusText, getInvoiceStatusText,
getPaymentStatusColor, getPaymentStatusColor,
getPaymentStatusText, getPaymentStatusText,
} from "../../../utils/erp"; } from '../../../utils/erp'
interface InvoiceManagementProps { interface InvoiceManagementProps {
invoices: FiInvoice[]; invoices: FiInvoice[]
onAdd: () => void; onAdd: () => void
onEdit: (invoice: FiInvoice) => void; onEdit: (invoice: FiInvoice) => void
onConvertFromWaybill: () => void; onConvertFromWaybill: () => void
onCreatePayment: (invoice: FiInvoice) => void; onCreatePayment: (invoice: FiInvoice) => void
onViewDetails: (invoice: FiInvoice) => void; onViewDetails: (invoice: FiInvoice) => void
} }
const InvoiceManagement: React.FC<InvoiceManagementProps> = ({ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
@ -43,103 +38,85 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
onCreatePayment, onCreatePayment,
onViewDetails, onViewDetails,
}) => { }) => {
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState('')
const [selectedType, setSelectedType] = useState<InvoiceTypeEnum | "all">( const [selectedType, setSelectedType] = useState<InvoiceTypeEnum | 'all'>('all')
"all" const [selectedStatus, setSelectedStatus] = useState<InvoiceStatusEnum | 'all'>('all')
); const [selectedPaymentStatus, setSelectedPaymentStatus] = useState<PaymentStatusEnum | 'all'>(
const [selectedStatus, setSelectedStatus] = useState< 'all',
InvoiceStatusEnum | "all" )
>("all"); const [sortBy, setSortBy] = useState<'date' | 'amount' | 'dueDate'>('date')
const [selectedPaymentStatus, setSelectedPaymentStatus] = useState<
PaymentStatusEnum | "all"
>("all");
const [sortBy, setSortBy] = useState<"date" | "amount" | "dueDate">("date");
const filteredInvoices = invoices const filteredInvoices = invoices
.filter((invoice) => { .filter((invoice) => {
if ( if (
searchTerm && searchTerm &&
!invoice.invoiceNumber !invoice.invoiceNumber.toLowerCase().includes(searchTerm.toLowerCase()) &&
.toLowerCase() !invoice.currentAccount?.accountCode?.toLowerCase().includes(searchTerm.toLowerCase()) &&
.includes(searchTerm.toLowerCase()) &&
!invoice.currentAccount?.accountCode
?.toLowerCase()
.includes(searchTerm.toLowerCase()) &&
!invoice.waybillNumber?.toLowerCase().includes(searchTerm.toLowerCase()) !invoice.waybillNumber?.toLowerCase().includes(searchTerm.toLowerCase())
) { ) {
return false; return false
} }
if (selectedType !== "all" && invoice.invoiceType !== selectedType) { if (selectedType !== 'all' && invoice.invoiceType !== selectedType) {
return false; return false
} }
if (selectedStatus !== "all" && invoice.status !== selectedStatus) { if (selectedStatus !== 'all' && invoice.status !== selectedStatus) {
return false; return false
} }
if ( if (selectedPaymentStatus !== 'all' && invoice.paymentStatus !== selectedPaymentStatus) {
selectedPaymentStatus !== "all" && return false
invoice.paymentStatus !== selectedPaymentStatus
) {
return false;
} }
return true; return true
}) })
.sort((a, b) => { .sort((a, b) => {
switch (sortBy) { switch (sortBy) {
case "date": case 'date':
return ( return new Date(b.invoiceDate).getTime() - new Date(a.invoiceDate).getTime()
new Date(b.invoiceDate).getTime() - case 'amount':
new Date(a.invoiceDate).getTime() return b.totalAmount - a.totalAmount
); case 'dueDate':
case "amount": return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime()
return b.totalAmount - a.totalAmount;
case "dueDate":
return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime();
default: default:
return 0; return 0
} }
}); })
const getDaysUntilDue = (dueDate: Date) => { const getDaysUntilDue = (dueDate: Date) => {
const today = new Date(); const today = new Date()
const due = new Date(dueDate); const due = new Date(dueDate)
const diffTime = due.getTime() - today.getTime(); const diffTime = due.getTime() - today.getTime()
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
return diffDays; return diffDays
}; }
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return amount.toLocaleString("tr-TR", { return amount.toLocaleString('tr-TR', {
style: "currency", style: 'currency',
currency: "TRY", currency: 'TRY',
minimumFractionDigits: 2, minimumFractionDigits: 2,
}); })
}; }
const columns: Column<FiInvoice>[] = [ const columns: Column<FiInvoice>[] = [
{ {
key: "invoiceNumber", key: 'invoiceNumber',
header: "Fatura No", header: 'Fatura No',
sortable: true, sortable: true,
render: (invoice: FiInvoice) => ( render: (invoice: FiInvoice) => (
<div> <div>
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">{invoice.invoiceNumber}</div>
{invoice.invoiceNumber}
</div>
{invoice.waybillNumber && ( {invoice.waybillNumber && (
<div className="text-sm text-gray-500"> <div className="text-sm text-gray-500">İrs: {invoice.waybillNumber}</div>
İrs: {invoice.waybillNumber}
</div>
)} )}
</div> </div>
), ),
}, },
{ {
key: "type", key: 'type',
header: "Tür", header: 'Tür',
render: (invoice: FiInvoice) => ( render: (invoice: FiInvoice) => (
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
invoice.invoiceType invoice.invoiceType,
)}`} )}`}
> >
{getInvoiceTypeText(invoice.invoiceType)} {getInvoiceTypeText(invoice.invoiceType)}
@ -147,61 +124,54 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
), ),
}, },
{ {
key: "currentAccount", key: 'currentAccount',
header: "Cari Hesap", header: 'Cari Hesap',
render: (invoice: FiInvoice) => ( render: (invoice: FiInvoice) => (
<div> <div>
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">
{invoice.currentAccount?.accountCode || "Bilinmeyen"} {invoice.currentAccount?.accountCode || 'Bilinmeyen'}
</div> </div>
</div> </div>
), ),
}, },
{ {
key: "dates", key: 'dates',
header: "Tarihler", header: 'Tarihler',
render: (invoice: FiInvoice) => { render: (invoice: FiInvoice) => {
const daysUntilDue = getDaysUntilDue(invoice.dueDate); const daysUntilDue = getDaysUntilDue(invoice.dueDate)
return ( return (
<div className="text-sm"> <div className="text-sm">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<FaCalendar className="w-3 h-3 text-gray-400" /> <FaCalendar className="w-3 h-3 text-gray-400" />
<span> <span>Fatura: {new Date(invoice.invoiceDate).toLocaleDateString('tr-TR')}</span>
Fatura:{" "}
{new Date(invoice.invoiceDate).toLocaleDateString("tr-TR")}
</span>
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<FaClock className="w-3 h-3 text-gray-400" /> <FaClock className="w-3 h-3 text-gray-400" />
<span <span
className={ className={
daysUntilDue < 0 daysUntilDue < 0
? "text-red-600" ? 'text-red-600'
: daysUntilDue <= 7 : daysUntilDue <= 7
? "text-orange-600" ? 'text-orange-600'
: "text-gray-600" : 'text-gray-600'
} }
> >
Vade: {new Date(invoice.dueDate).toLocaleDateString("tr-TR")} Vade: {new Date(invoice.dueDate).toLocaleDateString('tr-TR')}
</span> </span>
</div> </div>
{daysUntilDue < 0 && ( {daysUntilDue < 0 && (
<div className="text-xs text-red-600"> <div className="text-xs text-red-600">{Math.abs(daysUntilDue)} gün gecikme</div>
{Math.abs(daysUntilDue)} gün gecikme
</div>
)} )}
</div> </div>
); )
}, },
}, },
{ {
key: "amounts", key: 'amounts',
header: "Tutarlar", header: 'Tutarlar',
render: (invoice: FiInvoice) => ( render: (invoice: FiInvoice) => (
<div className="text-right"> <div className="text-right">
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">{formatCurrency(invoice.totalAmount)}</div>
{formatCurrency(invoice.totalAmount)}
</div>
{invoice.paidAmount > 0 && ( {invoice.paidAmount > 0 && (
<div className="text-sm text-green-600"> <div className="text-sm text-green-600">
Ödenen: {formatCurrency(invoice.paidAmount)} Ödenen: {formatCurrency(invoice.paidAmount)}
@ -216,13 +186,13 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
), ),
}, },
{ {
key: "status", key: 'status',
header: "Durum", header: 'Durum',
render: (invoice: FiInvoice) => ( render: (invoice: FiInvoice) => (
<div className="space-y-1"> <div className="space-y-1">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceStatusColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceStatusColor(
invoice.status invoice.status,
)}`} )}`}
> >
{getInvoiceStatusText(invoice.status)} {getInvoiceStatusText(invoice.status)}
@ -230,7 +200,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<br /> <br />
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
invoice.paymentStatus invoice.paymentStatus,
)}`} )}`}
> >
{getPaymentStatusText(invoice.paymentStatus)} {getPaymentStatusText(invoice.paymentStatus)}
@ -239,8 +209,8 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
), ),
}, },
{ {
key: "actions", key: 'actions',
header: "İşlemler", header: 'İşlemler',
render: (invoice: FiInvoice) => ( render: (invoice: FiInvoice) => (
<div className="flex gap-1"> <div className="flex gap-1">
{invoice.paymentStatus !== PaymentStatusEnum.Paid && ( {invoice.paymentStatus !== PaymentStatusEnum.Paid && (
@ -269,37 +239,33 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
</div> </div>
), ),
}, },
]; ]
// Calculate statistics // Calculate statistics
const totalInvoices = invoices.length; const totalInvoices = invoices.length
const totalSalesAmount = invoices const totalSalesAmount = invoices
.filter((i) => i.invoiceType === InvoiceTypeEnum.Sales) .filter((i) => i.invoiceType === InvoiceTypeEnum.Sales)
.reduce((sum, i) => sum + i.totalAmount, 0); .reduce((sum, i) => sum + i.totalAmount, 0)
const totalPurchaseAmount = invoices const totalPurchaseAmount = invoices
.filter((i) => i.invoiceType === InvoiceTypeEnum.Purchase) .filter((i) => i.invoiceType === InvoiceTypeEnum.Purchase)
.reduce((sum, i) => sum + i.totalAmount, 0); .reduce((sum, i) => sum + i.totalAmount, 0)
const totalUnpaidAmount = invoices const totalUnpaidAmount = invoices
.filter((i) => i.paymentStatus !== PaymentStatusEnum.Paid) .filter((i) => i.paymentStatus !== PaymentStatusEnum.Paid)
.reduce((sum, i) => sum + i.remainingAmount, 0); .reduce((sum, i) => sum + i.remainingAmount, 0)
// Overdue invoices // Overdue invoices
const overdueInvoices = invoices.filter( const overdueInvoices = invoices.filter(
(i) => (i) => i.paymentStatus !== PaymentStatusEnum.Paid && new Date(i.dueDate) < new Date(),
i.paymentStatus !== PaymentStatusEnum.Paid && )
new Date(i.dueDate) < new Date()
);
// Payment status distribution // Payment status distribution
const paymentDistribution = Object.values(PaymentStatusEnum).map( const paymentDistribution = Object.values(PaymentStatusEnum).map((status) => ({
(status) => ({ status,
status, count: invoices.filter((i) => i.paymentStatus === status).length,
count: invoices.filter((i) => i.paymentStatus === status).length, amount: invoices
amount: invoices .filter((i) => i.paymentStatus === status)
.filter((i) => i.paymentStatus === status) .reduce((sum, i) => sum + i.totalAmount, 0),
.reduce((sum, i) => sum + i.totalAmount, 0), }))
})
);
// Invoice type distribution // Invoice type distribution
const typeDistribution = Object.values(InvoiceTypeEnum).map((type) => ({ const typeDistribution = Object.values(InvoiceTypeEnum).map((type) => ({
@ -308,7 +274,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
amount: invoices amount: invoices
.filter((i) => i.invoiceType === type) .filter((i) => i.invoiceType === type)
.reduce((sum, i) => sum + i.totalAmount, 0), .reduce((sum, i) => sum + i.totalAmount, 0),
})); }))
return ( return (
<div className="space-y-2"> <div className="space-y-2">
@ -316,9 +282,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<h2 className="text-2xl font-bold text-gray-900">Fatura Yönetimi</h2> <h2 className="text-2xl font-bold text-gray-900">Fatura Yönetimi</h2>
<p className="text-gray-600"> <p className="text-gray-600">Alış ve satış faturaları yönetimi</p>
Alış ve satış faturaları yönetimi
</p>
</div> </div>
<div className="flex gap-2 text-sm"> <div className="flex gap-2 text-sm">
<button <button
@ -340,12 +304,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
{/* Stats Cards */} {/* Stats Cards */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4"> <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<Widget <Widget title="Toplam Fatura" value={totalInvoices} color="blue" icon="FaFileAlt" />
title="Toplam Fatura"
value={totalInvoices}
color="blue"
icon="FaFileAlt"
/>
<Widget <Widget
title="Satış Tutarı" title="Satış Tutarı"
@ -372,16 +331,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
{/* Distribution Charts */} {/* Distribution Charts */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-white rounded-lg shadow-sm border p-4"> <div className="bg-white rounded-lg shadow-sm border p-4">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">Fatura Türü Dağılımı</h3>
Fatura Türü Dağılımı
</h3>
<div className="space-y-2"> <div className="space-y-2">
{typeDistribution.map(({ type, count, amount }) => ( {typeDistribution.map(({ type, count, amount }) => (
<div key={type} className="flex items-center justify-between"> <div key={type} className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
type type,
)}`} )}`}
> >
{getInvoiceTypeText(type)} {getInvoiceTypeText(type)}
@ -399,16 +356,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
</div> </div>
<div className="bg-white rounded-lg shadow-sm border p-4"> <div className="bg-white rounded-lg shadow-sm border p-4">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">Ödeme Durumu Dağılımı</h3>
Ödeme Durumu Dağılımı
</h3>
<div className="space-y-2"> <div className="space-y-2">
{paymentDistribution.map(({ status, count, amount }) => ( {paymentDistribution.map(({ status, count, amount }) => (
<div key={status} className="flex items-center justify-between"> <div key={status} className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
status status,
)}`} )}`}
> >
{getPaymentStatusText(status)} {getPaymentStatusText(status)}
@ -431,20 +386,15 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<div className="bg-red-50 border border-red-200 rounded-lg p-3"> <div className="bg-red-50 border border-red-200 rounded-lg p-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<FaExclamationTriangle className="w-5 h-5 text-red-600" /> <FaExclamationTriangle className="w-5 h-5 text-red-600" />
<h3 className="text-base font-semibold text-red-900"> <h3 className="text-base font-semibold text-red-900">Vadesi Geçmiş Faturalar</h3>
Vadesi Geçmiş Faturalar
</h3>
</div> </div>
<p className="text-sm text-red-700 mt-1"> <p className="text-sm text-red-700 mt-1">
{overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam {overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam tutar:{' '}
tutar:{" "} {formatCurrency(overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0))}
{formatCurrency(
overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0)
)}
</p> </p>
<div className="mt-2 space-y-1.5"> <div className="mt-2 space-y-1.5">
{overdueInvoices.slice(0, 3).map((invoice) => { {overdueInvoices.slice(0, 3).map((invoice) => {
const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate)); const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate))
return ( return (
<div <div
@ -466,7 +416,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
</span> </span>
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
@ -487,9 +437,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<select <select
value={selectedType} value={selectedType}
onChange={(e) => onChange={(e) => setSelectedType(e.target.value as InvoiceTypeEnum | 'all')}
setSelectedType(e.target.value as InvoiceTypeEnum | "all")
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Türler</option> <option value="all">Tüm Türler</option>
@ -502,9 +450,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<select <select
value={selectedStatus} value={selectedStatus}
onChange={(e) => onChange={(e) => setSelectedStatus(e.target.value as InvoiceStatusEnum | 'all')}
setSelectedStatus(e.target.value as InvoiceStatusEnum | "all")
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
@ -517,11 +463,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<select <select
value={selectedPaymentStatus} value={selectedPaymentStatus}
onChange={(e) => onChange={(e) => setSelectedPaymentStatus(e.target.value as PaymentStatusEnum | 'all')}
setSelectedPaymentStatus(
e.target.value as PaymentStatusEnum | "all"
)
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Ödeme Durumları</option> <option value="all">Tüm Ödeme Durumları</option>
@ -534,9 +476,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
<select <select
value={sortBy} value={sortBy}
onChange={(e) => onChange={(e) => setSortBy(e.target.value as 'date' | 'amount' | 'dueDate')}
setSortBy(e.target.value as "date" | "amount" | "dueDate")
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="date">Tarihe Göre</option> <option value="date">Tarihe Göre</option>
@ -553,16 +493,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
{filteredInvoices.length === 0 && ( {filteredInvoices.length === 0 && (
<div className="text-center py-10"> <div className="text-center py-10">
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" /> <FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
<h3 className="text-base font-medium text-gray-900 mb-2"> <h3 className="text-base font-medium text-gray-900 mb-2">Fatura bulunamadı</h3>
Fatura bulunamadı
</h3>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Yeni bir fatura ekleyin veya arama kriterlerinizi değiştirin. Yeni bir fatura ekleyin veya arama kriterlerinizi değiştirin.
</p> </p>
</div> </div>
)} )}
</div> </div>
); )
}; }
export default InvoiceManagement; export default InvoiceManagement

View file

@ -1,20 +1,15 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaFileAlt, FaSave, FaTimes } from "react-icons/fa"; import { FaFileAlt, FaSave, FaTimes } from 'react-icons/fa'
import { import { PromissoryNote, NoteStatusEnum, FiCurrentAccount, TypeEnum } from '../../../types/fi'
PromissoryNote, import { getNoteStatusText, getTypeText } from '@/utils/erp'
NoteTypeEnum, import { mockCurrencies } from '@/mocks/mockCurrencies'
NoteStatusEnum,
FiCurrentAccount,
} from "../../../types/fi";
interface PromissoryNoteFormProps { interface PromissoryNoteFormProps {
note?: PromissoryNote; note?: PromissoryNote
currentAccounts: FiCurrentAccount[]; currentAccounts: FiCurrentAccount[]
onSave: ( onSave: (note: Omit<PromissoryNote, 'id' | 'creationTime' | 'lastModificationTime'>) => void
note: Omit<PromissoryNote, "id" | "creationTime" | "lastModificationTime"> onCancel: () => void
) => void; isOpen: boolean
onCancel: () => void;
isOpen: boolean;
} }
const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
@ -25,21 +20,21 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
isOpen, isOpen,
}) => { }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
noteNumber: "", noteNumber: '',
drawerName: "", drawerName: '',
payeeName: "", payeeName: '',
currentAccountId: "", currentAccountId: '',
issueDate: new Date().toISOString().split("T")[0], issueDate: new Date().toISOString().split('T')[0],
dueDate: new Date().toISOString().split("T")[0], dueDate: new Date().toISOString().split('T')[0],
amount: 0, amount: 0,
currency: "TRY", currency: 'TRY',
status: NoteStatusEnum.InHand, status: NoteStatusEnum.InHand,
type: NoteTypeEnum.Received, type: TypeEnum.Received,
location: "", location: '',
notes: "", notes: '',
}); })
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({})
useEffect(() => { useEffect(() => {
if (note) { if (note) {
@ -47,60 +42,60 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
noteNumber: note.noteNumber, noteNumber: note.noteNumber,
drawerName: note.drawerName, drawerName: note.drawerName,
payeeName: note.payeeName, payeeName: note.payeeName,
currentAccountId: note.currentAccountId || "", currentAccountId: note.currentAccountId || '',
issueDate: new Date(note.issueDate).toISOString().split("T")[0], issueDate: new Date(note.issueDate).toISOString().split('T')[0],
dueDate: new Date(note.dueDate).toISOString().split("T")[0], dueDate: new Date(note.dueDate).toISOString().split('T')[0],
amount: note.amount, amount: note.amount,
currency: note.currency, currency: note.currency,
status: note.status, status: note.status,
type: note.type, type: note.type,
location: note.location || "", location: note.location || '',
notes: note.notes || "", notes: note.notes || '',
}); })
} else { } else {
setFormData({ setFormData({
noteNumber: "", noteNumber: '',
drawerName: "", drawerName: '',
payeeName: "", payeeName: '',
currentAccountId: "", currentAccountId: '',
issueDate: new Date().toISOString().split("T")[0], issueDate: new Date().toISOString().split('T')[0],
dueDate: new Date().toISOString().split("T")[0], dueDate: new Date().toISOString().split('T')[0],
amount: 0, amount: 0,
currency: "TRY", currency: 'TRY',
status: NoteStatusEnum.InHand, status: NoteStatusEnum.InHand,
type: NoteTypeEnum.Received, type: TypeEnum.Received,
location: "", location: '',
notes: "", notes: '',
}); })
} }
setErrors({}); setErrors({})
}, [note, isOpen]); }, [note, isOpen])
const validateForm = () => { const validateForm = () => {
const newErrors: Record<string, string> = {}; const newErrors: Record<string, string> = {}
if (!formData.noteNumber.trim()) { if (!formData.noteNumber.trim()) {
newErrors.noteNumber = "Senet numarası gereklidir"; newErrors.noteNumber = 'Senet numarası gereklidir'
} }
if (!formData.drawerName.trim()) { if (!formData.drawerName.trim()) {
newErrors.drawerName = "Keşideci adı gereklidir"; newErrors.drawerName = 'Keşideci adı gereklidir'
} }
if (!formData.payeeName.trim()) { if (!formData.payeeName.trim()) {
newErrors.payeeName = "Lehtar adı gereklidir"; newErrors.payeeName = 'Lehtar adı gereklidir'
} }
if (formData.amount <= 0) { if (formData.amount <= 0) {
newErrors.amount = "Tutar 0'dan büyük olmalıdır"; newErrors.amount = "Tutar 0'dan büyük olmalıdır"
} }
if (new Date(formData.dueDate) < new Date(formData.issueDate)) { if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
newErrors.dueDate = "Vade tarihi düzenleme tarihinden sonra olmalıdır"; newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
} }
setErrors(newErrors); setErrors(newErrors)
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (validateForm()) { if (validateForm()) {
const noteData = { const noteData = {
...formData, ...formData,
@ -109,22 +104,19 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
currentAccount: formData.currentAccountId currentAccount: formData.currentAccountId
? currentAccounts.find((acc) => acc.id === formData.currentAccountId) ? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
: undefined, : undefined,
}; }
onSave(noteData); onSave(noteData)
} }
}; }
const handleInputChange = ( const handleInputChange = (field: string, value: string | number | TypeEnum | NoteStatusEnum) => {
field: string, setFormData((prev) => ({ ...prev, [field]: value }))
value: string | number | NoteTypeEnum | NoteStatusEnum
) => {
setFormData((prev) => ({ ...prev, [field]: value }));
if (errors[field]) { if (errors[field]) {
setErrors((prev) => ({ ...prev, [field]: "" })); setErrors((prev) => ({ ...prev, [field]: '' }))
} }
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
@ -133,13 +125,10 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
<div className="flex items-center gap-2.5"> <div className="flex items-center gap-2.5">
<FaFileAlt className="w-5 h-5 text-green-600" /> <FaFileAlt className="w-5 h-5 text-green-600" />
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{note ? "Senet Düzenle" : "Yeni Senet"} {note ? 'Senet Düzenle' : 'Yeni Senet'}
</h2> </h2>
</div> </div>
<button <button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
onClick={onCancel}
className="p-2 hover:bg-gray-100 rounded-md"
>
<FaTimes className="w-5 h-5 text-gray-500" /> <FaTimes className="w-5 h-5 text-gray-500" />
</button> </button>
</div> </div>
@ -154,11 +143,9 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
<input <input
type="text" type="text"
value={formData.noteNumber} value={formData.noteNumber}
onChange={(e) => onChange={(e) => handleInputChange('noteNumber', e.target.value)}
handleInputChange("noteNumber", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
errors.noteNumber ? "border-red-500" : "border-gray-300" errors.noteNumber ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Senet numarasını giriniz" placeholder="Senet numarasını giriniz"
/> />
@ -168,100 +155,77 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
Tür *
</label>
<select <select
value={formData.type} value={formData.type}
onChange={(e) => onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
handleInputChange("type", e.target.value as NoteTypeEnum)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
> >
<option value={NoteTypeEnum.Received}>Alınan Senet</option> {Object.values(TypeEnum).map((type) => (
<option value={NoteTypeEnum.Issued}>Verilen Senet</option> <option key={type} value={type}>
{getTypeText(type)}
</option>
))}
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
Durum
</label>
<select <select
value={formData.status} value={formData.status}
onChange={(e) => onChange={(e) => handleInputChange('status', e.target.value as NoteStatusEnum)}
handleInputChange("status", e.target.value as NoteStatusEnum)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
> >
<option value={NoteStatusEnum.InHand}>Elde</option> {Object.values(NoteStatusEnum).map((status) => (
<option value={NoteStatusEnum.Collected}>Tahsil Edildi</option> <option key={status} value={status}>
<option value={NoteStatusEnum.Overdue}>Vadesi Geçmiş</option> {getNoteStatusText(status)}
<option value={NoteStatusEnum.Endorsed}>Ciro Edildi</option> </option>
<option value={NoteStatusEnum.Cancelled}>İptal</option> ))}
</select> </select>
</div> </div>
</div> </div>
{/* Taraf Bilgileri */} {/* Taraf Bilgileri */}
<div className="bg-gray-50 p-3 rounded-lg"> <div className="bg-gray-50 p-3 rounded-lg">
<h3 className="text-base font-medium text-gray-900 mb-3"> <h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
Taraf Bilgileri
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3"> <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
Keşideci *
</label>
<input <input
type="text" type="text"
value={formData.drawerName} value={formData.drawerName}
onChange={(e) => onChange={(e) => handleInputChange('drawerName', e.target.value)}
handleInputChange("drawerName", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
errors.drawerName ? "border-red-500" : "border-gray-300" errors.drawerName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Keşideci adını giriniz" placeholder="Keşideci adını giriniz"
/> />
{errors.drawerName && ( {errors.drawerName && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
{errors.drawerName}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
Lehtar *
</label>
<input <input
type="text" type="text"
value={formData.payeeName} value={formData.payeeName}
onChange={(e) => onChange={(e) => handleInputChange('payeeName', e.target.value)}
handleInputChange("payeeName", e.target.value)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
errors.payeeName ? "border-red-500" : "border-gray-300" errors.payeeName ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Lehtar adını giriniz" placeholder="Lehtar adını giriniz"
/> />
{errors.payeeName && ( {errors.payeeName && (
<p className="text-red-500 text-xs mt-1"> <p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
{errors.payeeName}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
Cari Hesap
</label>
<select <select
value={formData.currentAccountId} value={formData.currentAccountId}
onChange={(e) => onChange={(e) => handleInputChange('currentAccountId', e.target.value)}
handleInputChange("currentAccountId", e.target.value)
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
> >
<option value="">Cari hesap seçiniz</option> <option value="">Cari hesap seçiniz</option>
@ -278,39 +242,33 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
{/* Tutar ve Tarih Bilgileri */} {/* Tutar ve Tarih Bilgileri */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
Tutar *
</label>
<input <input
type="number" type="number"
step="0.01" step="0.01"
min="0" min="0"
value={formData.amount} value={formData.amount}
onChange={(e) => onChange={(e) => handleInputChange('amount', parseFloat(e.target.value) || 0)}
handleInputChange("amount", parseFloat(e.target.value) || 0)
}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
errors.amount ? "border-red-500" : "border-gray-300" errors.amount ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="0.00" placeholder="0.00"
/> />
{errors.amount && ( {errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
<p className="text-red-500 text-xs mt-1">{errors.amount}</p>
)}
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
Para Birimi
</label>
<select <select
value={formData.currency} value={formData.currency}
onChange={(e) => handleInputChange("currency", e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
@ -321,38 +279,32 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
<input <input
type="date" type="date"
value={formData.issueDate} value={formData.issueDate}
onChange={(e) => handleInputChange("issueDate", e.target.value)} onChange={(e) => handleInputChange('issueDate', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
Vade Tarihi *
</label>
<input <input
type="date" type="date"
value={formData.dueDate} value={formData.dueDate}
onChange={(e) => handleInputChange("dueDate", e.target.value)} onChange={(e) => handleInputChange('dueDate', e.target.value)}
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${ className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
errors.dueDate ? "border-red-500" : "border-gray-300" errors.dueDate ? 'border-red-500' : 'border-gray-300'
}`} }`}
/> />
{errors.dueDate && ( {errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
<p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>
)}
</div> </div>
</div> </div>
{/* Konum */} {/* Konum */}
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Konum</label>
Konum
</label>
<input <input
type="text" type="text"
value={formData.location} value={formData.location}
onChange={(e) => handleInputChange("location", e.target.value)} onChange={(e) => handleInputChange('location', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Senetin bulunduğu konum" placeholder="Senetin bulunduğu konum"
/> />
@ -360,12 +312,10 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
{/* Notlar */} {/* Notlar */}
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
Notlar
</label>
<textarea <textarea
value={formData.notes} value={formData.notes}
onChange={(e) => handleInputChange("notes", e.target.value)} onChange={(e) => handleInputChange('notes', e.target.value)}
rows={3} rows={3}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Ek notlar..." placeholder="Ek notlar..."
@ -386,13 +336,13 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors" className="flex items-center gap-2 px-4 py-1.5 text-sm bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{note ? "Güncelle" : "Kaydet"} {note ? 'Güncelle' : 'Kaydet'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default PromissoryNoteForm; export default PromissoryNoteForm

View file

@ -1,178 +1,161 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaSave, FaTimes, FaPlus, FaTrash, FaTruck } from "react-icons/fa"; import { FaSave, FaTimes, FaPlus, FaTrash, FaTruck } from 'react-icons/fa'
import { import { FiWaybill, FiWaybillItem, WaybillTypeEnum, WaybillStatusEnum } from '../../../types/fi'
FiWaybill, import { mockCurrentAccounts } from '../../../mocks/mockCurrentAccounts'
FiWaybillItem, import { getWaybillStatusText, getWaybillTypeText } from '@/utils/erp'
WaybillTypeEnum,
WaybillStatusEnum,
} from "../../../types/fi";
import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts";
interface WaybillFormProps { interface WaybillFormProps {
waybill?: FiWaybill; waybill?: FiWaybill
onSave: (waybill: Partial<FiWaybill>) => void; onSave: (waybill: Partial<FiWaybill>) => void
onCancel: () => void; onCancel: () => void
isVisible: boolean; isVisible: boolean
} }
const WaybillForm: React.FC<WaybillFormProps> = ({ const WaybillForm: React.FC<WaybillFormProps> = ({ waybill, onSave, onCancel, isVisible }) => {
waybill,
onSave,
onCancel,
isVisible,
}) => {
const [formData, setFormData] = useState<Partial<FiWaybill>>({ const [formData, setFormData] = useState<Partial<FiWaybill>>({
waybillNumber: "", waybillNumber: '',
waybillType: WaybillTypeEnum.Outgoing, waybillType: WaybillTypeEnum.Outgoing,
currentAccountId: "", currentAccountId: '',
waybillDate: new Date(), waybillDate: new Date(),
deliveryDate: new Date(), deliveryDate: new Date(),
subtotal: 0, subtotal: 0,
taxAmount: 0, taxAmount: 0,
discountAmount: 0, discountAmount: 0,
totalAmount: 0, totalAmount: 0,
currency: "TRY", currency: 'TRY',
status: WaybillStatusEnum.Draft, status: WaybillStatusEnum.Draft,
isInvoiced: false, isInvoiced: false,
items: [], items: [],
deliveryAddress: "", deliveryAddress: '',
receiverName: "", receiverName: '',
receiverPhone: "", receiverPhone: '',
carrierCompany: "", carrierCompany: '',
trackingNumber: "", trackingNumber: '',
notes: "", notes: '',
}); })
const [newItem, setNewItem] = useState<Partial<FiWaybillItem>>({ const [newItem, setNewItem] = useState<Partial<FiWaybillItem>>({
description: "", description: '',
quantity: 1, quantity: 1,
unitPrice: 0, unitPrice: 0,
taxRate: 18, taxRate: 18,
discountRate: 0, discountRate: 0,
unit: "Adet", unit: 'Adet',
}); })
useEffect(() => { useEffect(() => {
if (waybill) { if (waybill) {
setFormData({ setFormData({
...waybill, ...waybill,
waybillDate: new Date(waybill.waybillDate), waybillDate: new Date(waybill.waybillDate),
deliveryDate: waybill.deliveryDate deliveryDate: waybill.deliveryDate ? new Date(waybill.deliveryDate) : new Date(),
? new Date(waybill.deliveryDate) })
: new Date(),
});
} else { } else {
// Generate new waybill number // Generate new waybill number
const now = new Date(); const now = new Date()
const year = now.getFullYear(); const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, "0"); const month = String(now.getMonth() + 1).padStart(2, '0')
const waybillNumber = `IRS${year}${month}${String( const waybillNumber = `IRS${year}${month}${String(Math.floor(Math.random() * 10000)).padStart(
Math.floor(Math.random() * 10000) 4,
).padStart(4, "0")}`; '0',
)}`
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
waybillNumber, waybillNumber,
waybillDate: now, waybillDate: now,
deliveryDate: now, deliveryDate: now,
})); }))
} }
}, [waybill]); }, [waybill])
const calculateItemTotal = (item: Partial<FiWaybillItem>) => { const calculateItemTotal = (item: Partial<FiWaybillItem>) => {
const subtotal = (item.quantity || 0) * (item.unitPrice || 0); const subtotal = (item.quantity || 0) * (item.unitPrice || 0)
const discountAmount = subtotal * ((item.discountRate || 0) / 100); const discountAmount = subtotal * ((item.discountRate || 0) / 100)
const taxableAmount = subtotal - discountAmount; const taxableAmount = subtotal - discountAmount
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100); const taxAmount = taxableAmount * ((item.taxRate || 0) / 100)
return taxableAmount + taxAmount; return taxableAmount + taxAmount
}; }
const calculateWaybillTotals = (items: FiWaybillItem[]) => { const calculateWaybillTotals = (items: FiWaybillItem[]) => {
const subtotal = items.reduce( const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0)
(sum, item) => sum + item.quantity * item.unitPrice, const discountAmount = items.reduce((sum, item) => sum + item.discountAmount, 0)
0 const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0)
); const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0)
const discountAmount = items.reduce(
(sum, item) => sum + item.discountAmount,
0
);
const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0);
const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0);
return { return {
subtotal, subtotal,
discountAmount, discountAmount,
taxAmount, taxAmount,
totalAmount, totalAmount,
}; }
}; }
const handleAddItem = () => { const handleAddItem = () => {
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) { if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
alert("Lütfen ürün bilgilerini doldurun"); alert('Lütfen ürün bilgilerini doldurun')
return; return
} }
const subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0); const subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0)
const discountAmount = subtotal * ((newItem.discountRate || 0) / 100); const discountAmount = subtotal * ((newItem.discountRate || 0) / 100)
const taxableAmount = subtotal - discountAmount; const taxableAmount = subtotal - discountAmount
const taxAmount = taxableAmount * ((newItem.taxRate || 0) / 100); const taxAmount = taxableAmount * ((newItem.taxRate || 0) / 100)
const item: FiWaybillItem = { const item: FiWaybillItem = {
id: Date.now().toString(), id: Date.now().toString(),
waybillId: formData.id || "", waybillId: formData.id || '',
description: newItem.description!, description: newItem.description!,
quantity: newItem.quantity!, quantity: newItem.quantity!,
unitPrice: newItem.unitPrice!, unitPrice: newItem.unitPrice!,
unit: newItem.unit || "Adet", unit: newItem.unit || 'Adet',
taxRate: newItem.taxRate || 18, taxRate: newItem.taxRate || 18,
discountRate: newItem.discountRate || 0, discountRate: newItem.discountRate || 0,
lineTotal: calculateItemTotal(newItem), lineTotal: calculateItemTotal(newItem),
discountAmount, discountAmount,
taxAmount, taxAmount,
netAmount: taxableAmount, netAmount: taxableAmount,
}; }
const updatedItems = [...(formData.items || []), item]; const updatedItems = [...(formData.items || []), item]
const totals = calculateWaybillTotals(updatedItems); const totals = calculateWaybillTotals(updatedItems)
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
items: updatedItems, items: updatedItems,
...totals, ...totals,
})); }))
setNewItem({ setNewItem({
description: "", description: '',
quantity: 1, quantity: 1,
unitPrice: 0, unitPrice: 0,
taxRate: 18, taxRate: 18,
discountRate: 0, discountRate: 0,
unit: "Adet", unit: 'Adet',
}); })
}; }
const handleRemoveItem = (itemId: string) => { const handleRemoveItem = (itemId: string) => {
const updatedItems = const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []
formData.items?.filter((item) => item.id !== itemId) || []; const totals = calculateWaybillTotals(updatedItems)
const totals = calculateWaybillTotals(updatedItems);
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
items: updatedItems, items: updatedItems,
...totals, ...totals,
})); }))
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (!formData.currentAccountId) { if (!formData.currentAccountId) {
alert("Lütfen cari hesap seçin"); alert('Lütfen cari hesap seçin')
return; return
} }
if (!formData.items?.length) { if (!formData.items?.length) {
alert("Lütfen en az bir ürün ekleyin"); alert('Lütfen en az bir ürün ekleyin')
return; return
} }
onSave({ onSave({
@ -180,18 +163,18 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
id: waybill?.id || Date.now().toString(), id: waybill?.id || Date.now().toString(),
creationTime: waybill?.creationTime || new Date(), creationTime: waybill?.creationTime || new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}); })
}; }
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return amount.toLocaleString("tr-TR", { return amount.toLocaleString('tr-TR', {
style: "currency", style: 'currency',
currency: "TRY", currency: 'TRY',
minimumFractionDigits: 2, minimumFractionDigits: 2,
}); })
}; }
if (!isVisible) return null; if (!isVisible) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"> <div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
@ -201,7 +184,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
<div className="flex items-center gap-2.5"> <div className="flex items-center gap-2.5">
<FaTruck className="w-5 h-5 text-blue-600" /> <FaTruck className="w-5 h-5 text-blue-600" />
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{waybill ? "İrsaliye Düzenle" : "Yeni İrsaliye"} {waybill ? 'İrsaliye Düzenle' : 'Yeni İrsaliye'}
</h2> </h2>
</div> </div>
<button <button
@ -217,24 +200,18 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
{/* Basic Information */} {/* Basic Information */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye No</label>
İrsaliye No
</label>
<input <input
type="text" type="text"
value={formData.waybillNumber} value={formData.waybillNumber}
onChange={(e) => onChange={(e) => setFormData({ ...formData, waybillNumber: e.target.value })}
setFormData({ ...formData, waybillNumber: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required required
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye Türü</label>
İrsaliye Türü
</label>
<select <select
value={formData.waybillType} value={formData.waybillType}
onChange={(e) => onChange={(e) =>
@ -245,23 +222,16 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={WaybillTypeEnum.Outgoing}> {Object.values(WaybillTypeEnum).map((type) => (
Çıkış İrsaliyesi <option key={type} value={type}>
</option> {getWaybillTypeText(type)}
<option value={WaybillTypeEnum.Incoming}> </option>
Giriş İrsaliyesi ))}
</option>
<option value={WaybillTypeEnum.Transfer}>
Transfer İrsaliyesi
</option>
<option value={WaybillTypeEnum.Return}>İade İrsaliyesi</option>
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Durum</label>
Durum
</label>
<select <select
value={formData.status} value={formData.status}
onChange={(e) => onChange={(e) =>
@ -272,24 +242,19 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={WaybillStatusEnum.Draft}>Taslak</option> {Object.values(WaybillStatusEnum).map((status) => (
<option value={WaybillStatusEnum.Confirmed}>Onaylandı</option> <option key={status} value={status}>
<option value={WaybillStatusEnum.Delivered}> {getWaybillStatusText(status)}
Teslim Edildi </option>
</option> ))}
<option value={WaybillStatusEnum.Cancelled}>İptal</option>
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Cari Hesap</label>
Cari Hesap
</label>
<select <select
value={formData.currentAccountId} value={formData.currentAccountId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, currentAccountId: e.target.value })}
setFormData({ ...formData, currentAccountId: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required required
> >
@ -308,7 +273,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</label> </label>
<input <input
type="date" type="date"
value={formData.waybillDate?.toISOString().split("T")[0]} value={formData.waybillDate?.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -321,12 +286,10 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Teslim Tarihi</label>
Teslim Tarihi
</label>
<input <input
type="date" type="date"
value={formData.deliveryDate?.toISOString().split("T")[0]} value={formData.deliveryDate?.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -340,16 +303,14 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
{/* Delivery Information */} {/* Delivery Information */}
<div className="mb-6"> <div className="mb-6">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">Teslimat Bilgileri</h3>
Teslimat Bilgileri
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">
Teslimat Adresi Teslimat Adresi
</label> </label>
<textarea <textarea
value={formData.deliveryAddress || ""} value={formData.deliveryAddress || ''}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -362,15 +323,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</div> </div>
<div className="space-y-3"> <div className="space-y-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Alıcı Adı</label>
Alıcı Adı
</label>
<input <input
type="text" type="text"
value={formData.receiverName || ""} value={formData.receiverName || ''}
onChange={(e) => onChange={(e) => setFormData({ ...formData, receiverName: e.target.value })}
setFormData({ ...formData, receiverName: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
@ -380,7 +337,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</label> </label>
<input <input
type="text" type="text"
value={formData.receiverPhone || ""} value={formData.receiverPhone || ''}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -397,10 +354,8 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</label> </label>
<input <input
type="text" type="text"
value={formData.carrierCompany || ""} value={formData.carrierCompany || ''}
onChange={(e) => onChange={(e) => setFormData({ ...formData, carrierCompany: e.target.value })}
setFormData({ ...formData, carrierCompany: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
@ -410,10 +365,8 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</label> </label>
<input <input
type="text" type="text"
value={formData.trackingNumber || ""} value={formData.trackingNumber || ''}
onChange={(e) => onChange={(e) => setFormData({ ...formData, trackingNumber: e.target.value })}
setFormData({ ...formData, trackingNumber: e.target.value })
}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
@ -422,9 +375,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
{/* Waybill Items */} {/* Waybill Items */}
<div className="mb-6"> <div className="mb-6">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">İrsaliye Kalemleri</h3>
İrsaliye Kalemleri
</h3>
{/* Add New Item */} {/* Add New Item */}
<div className="bg-gray-50 p-3 rounded-lg mb-3"> <div className="bg-gray-50 p-3 rounded-lg mb-3">
@ -435,21 +386,17 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</label> </label>
<input <input
type="text" type="text"
value={newItem.description || ""} value={newItem.description || ''}
onChange={(e) => onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
setNewItem({ ...newItem, description: e.target.value })
}
className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Ürün/Hizmet açıklaması" placeholder="Ürün/Hizmet açıklaması"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Miktar</label>
Miktar
</label>
<input <input
type="number" type="number"
value={newItem.quantity || ""} value={newItem.quantity || ''}
onChange={(e) => onChange={(e) =>
setNewItem({ setNewItem({
...newItem, ...newItem,
@ -462,15 +409,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Birim</label>
Birim
</label>
<input <input
type="text" type="text"
value={newItem.unit || ""} value={newItem.unit || ''}
onChange={(e) => onChange={(e) => setNewItem({ ...newItem, unit: e.target.value })}
setNewItem({ ...newItem, unit: e.target.value })
}
className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Adet" placeholder="Adet"
/> />
@ -481,7 +424,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</label> </label>
<input <input
type="number" type="number"
value={newItem.unitPrice || ""} value={newItem.unitPrice || ''}
onChange={(e) => onChange={(e) =>
setNewItem({ setNewItem({
...newItem, ...newItem,
@ -535,15 +478,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
<tbody className="divide-y divide-gray-200"> <tbody className="divide-y divide-gray-200">
{formData.items.map((item) => ( {formData.items.map((item) => (
<tr key={item.id} className="text-sm"> <tr key={item.id} className="text-sm">
<td className="px-3 py-2 text-gray-900"> <td className="px-3 py-2 text-gray-900">{item.description}</td>
{item.description}
</td>
<td className="px-3 py-2 text-gray-900 text-right"> <td className="px-3 py-2 text-gray-900 text-right">
{item.quantity.toLocaleString("tr-TR")} {item.quantity.toLocaleString('tr-TR')}
</td>
<td className="px-3 py-2 text-gray-900 text-center">
{item.unit}
</td> </td>
<td className="px-3 py-2 text-gray-900 text-center">{item.unit}</td>
<td className="px-3 py-2 text-gray-900 text-right"> <td className="px-3 py-2 text-gray-900 text-right">
{formatCurrency(item.unitPrice)} {formatCurrency(item.unitPrice)}
</td> </td>
@ -571,14 +510,10 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
<div className="bg-gray-50 p-4 rounded-lg mb-4"> <div className="bg-gray-50 p-4 rounded-lg mb-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Notlar</label>
Notlar
</label>
<textarea <textarea
value={formData.notes || ""} value={formData.notes || ''}
onChange={(e) => onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
setFormData({ ...formData, notes: e.target.value })
}
rows={4} rows={4}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="İrsaliye ile ilgili notlar..." placeholder="İrsaliye ile ilgili notlar..."
@ -587,9 +522,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
<div className="space-y-2 text-sm"> <div className="space-y-2 text-sm">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm text-gray-600">Ara Toplam:</span> <span className="text-sm text-gray-600">Ara Toplam:</span>
<span className="font-medium"> <span className="font-medium">{formatCurrency(formData.subtotal || 0)}</span>
{formatCurrency(formData.subtotal || 0)}
</span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm text-gray-600">İndirim:</span> <span className="text-sm text-gray-600">İndirim:</span>
@ -599,15 +532,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm text-gray-600">KDV:</span> <span className="text-sm text-gray-600">KDV:</span>
<span className="font-medium"> <span className="font-medium">{formatCurrency(formData.taxAmount || 0)}</span>
{formatCurrency(formData.taxAmount || 0)}
</span>
</div> </div>
<div className="border-t pt-3"> <div className="border-t pt-3">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-base font-semibold text-gray-900"> <span className="text-base font-semibold text-gray-900">Genel Toplam:</span>
Genel Toplam:
</span>
<span className="text-base font-bold text-blue-600"> <span className="text-base font-bold text-blue-600">
{formatCurrency(formData.totalAmount || 0)} {formatCurrency(formData.totalAmount || 0)}
</span> </span>
@ -631,13 +560,13 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2" className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{waybill ? "Güncelle" : "Kaydet"} {waybill ? 'Güncelle' : 'Kaydet'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default WaybillForm; export default WaybillForm

View file

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import { import {
FaPlus, FaPlus,
FaSearch, FaSearch,
@ -9,28 +9,24 @@ import {
FaTruck, FaTruck,
FaCheck, FaCheck,
FaEye, FaEye,
} from "react-icons/fa"; } from 'react-icons/fa'
import { import { FiWaybill, WaybillTypeEnum, WaybillStatusEnum } from '../../../types/fi'
FiWaybill, import DataTable, { Column } from '../../../components/common/DataTable'
WaybillTypeEnum, import Widget from '../../../components/common/Widget'
WaybillStatusEnum,
} from "../../../types/fi";
import DataTable, { Column } from "../../../components/common/DataTable";
import Widget from "../../../components/common/Widget";
import { import {
getWaybillStatusColor, getWaybillStatusColor,
getWaybillStatusText, getWaybillStatusText,
getWaybillTypeColor, getWaybillTypeColor,
getWaybillTypeText, getWaybillTypeText,
} from "../../../utils/erp"; } from '../../../utils/erp'
interface WaybillManagementProps { interface WaybillManagementProps {
waybills: FiWaybill[]; waybills: FiWaybill[]
onAdd: () => void; onAdd: () => void
onEdit: (waybill: FiWaybill) => void; onEdit: (waybill: FiWaybill) => void
onViewDetails: (waybill: FiWaybill) => void; onViewDetails: (waybill: FiWaybill) => void
onCreateInvoice: (waybill: FiWaybill) => void; onCreateInvoice: (waybill: FiWaybill) => void
onMarkAsDelivered: (waybill: FiWaybill) => void; onMarkAsDelivered: (waybill: FiWaybill) => void
} }
const WaybillManagement: React.FC<WaybillManagementProps> = ({ const WaybillManagement: React.FC<WaybillManagementProps> = ({
@ -41,109 +37,87 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
onCreateInvoice, onCreateInvoice,
onMarkAsDelivered, onMarkAsDelivered,
}) => { }) => {
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState('')
const [selectedType, setSelectedType] = useState<WaybillTypeEnum | "all">( const [selectedType, setSelectedType] = useState<WaybillTypeEnum | 'all'>('all')
"all" const [selectedStatus, setSelectedStatus] = useState<WaybillStatusEnum | 'all'>('all')
); const [showInvoicedOnly, setShowInvoicedOnly] = useState<'all' | 'invoiced' | 'not_invoiced'>(
const [selectedStatus, setSelectedStatus] = useState< 'not_invoiced',
WaybillStatusEnum | "all" )
>("all"); const [sortBy, setSortBy] = useState<'date' | 'amount' | 'deliveryDate'>('date')
const [showInvoicedOnly, setShowInvoicedOnly] = useState<
"all" | "invoiced" | "not_invoiced"
>("not_invoiced");
const [sortBy, setSortBy] = useState<"date" | "amount" | "deliveryDate">(
"date"
);
const filteredWaybills = waybills const filteredWaybills = waybills
.filter((waybill) => { .filter((waybill) => {
if ( if (
searchTerm && searchTerm &&
!waybill.waybillNumber !waybill.waybillNumber.toLowerCase().includes(searchTerm.toLowerCase()) &&
.toLowerCase() !waybill.currentAccount?.accountCode?.toLowerCase().includes(searchTerm.toLowerCase()) &&
.includes(searchTerm.toLowerCase()) && !waybill.trackingNumber?.toLowerCase().includes(searchTerm.toLowerCase())
!waybill.currentAccount?.accountCode
?.toLowerCase()
.includes(searchTerm.toLowerCase()) &&
!waybill.trackingNumber
?.toLowerCase()
.includes(searchTerm.toLowerCase())
) { ) {
return false; return false
} }
if (selectedType !== "all" && waybill.waybillType !== selectedType) { if (selectedType !== 'all' && waybill.waybillType !== selectedType) {
return false; return false
} }
if (selectedStatus !== "all" && waybill.status !== selectedStatus) { if (selectedStatus !== 'all' && waybill.status !== selectedStatus) {
return false; return false
} }
if (showInvoicedOnly === "invoiced" && !waybill.isInvoiced) { if (showInvoicedOnly === 'invoiced' && !waybill.isInvoiced) {
return false; return false
} }
if (showInvoicedOnly === "not_invoiced" && waybill.isInvoiced) { if (showInvoicedOnly === 'not_invoiced' && waybill.isInvoiced) {
return false; return false
} }
return true; return true
}) })
.sort((a, b) => { .sort((a, b) => {
switch (sortBy) { switch (sortBy) {
case "date": case 'date':
return ( return new Date(b.waybillDate).getTime() - new Date(a.waybillDate).getTime()
new Date(b.waybillDate).getTime() - case 'amount':
new Date(a.waybillDate).getTime() return b.totalAmount - a.totalAmount
); case 'deliveryDate':
case "amount": if (!a.deliveryDate && !b.deliveryDate) return 0
return b.totalAmount - a.totalAmount; if (!a.deliveryDate) return 1
case "deliveryDate": if (!b.deliveryDate) return -1
if (!a.deliveryDate && !b.deliveryDate) return 0; return new Date(a.deliveryDate).getTime() - new Date(b.deliveryDate).getTime()
if (!a.deliveryDate) return 1;
if (!b.deliveryDate) return -1;
return (
new Date(a.deliveryDate).getTime() -
new Date(b.deliveryDate).getTime()
);
default: default:
return 0; return 0
} }
}); })
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return amount.toLocaleString("tr-TR", { return amount.toLocaleString('tr-TR', {
style: "currency", style: 'currency',
currency: "TRY", currency: 'TRY',
minimumFractionDigits: 2, minimumFractionDigits: 2,
}); })
}; }
const formatDate = (date: Date) => { const formatDate = (date: Date) => {
return new Date(date).toLocaleDateString("tr-TR"); return new Date(date).toLocaleDateString('tr-TR')
}; }
const columns: Column<FiWaybill>[] = [ const columns: Column<FiWaybill>[] = [
{ {
key: "waybillNumber", key: 'waybillNumber',
header: "İrsaliye No", header: 'İrsaliye No',
sortable: true, sortable: true,
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div> <div>
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">{waybill.waybillNumber}</div>
{waybill.waybillNumber}
</div>
{waybill.trackingNumber && ( {waybill.trackingNumber && (
<div className="text-sm text-gray-500"> <div className="text-sm text-gray-500">Takip: {waybill.trackingNumber}</div>
Takip: {waybill.trackingNumber}
</div>
)} )}
</div> </div>
), ),
}, },
{ {
key: "type", key: 'type',
header: "Tür", header: 'Tür',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
waybill.waybillType waybill.waybillType,
)}`} )}`}
> >
{getWaybillTypeText(waybill.waybillType)} {getWaybillTypeText(waybill.waybillType)}
@ -151,22 +125,20 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
), ),
}, },
{ {
key: "currentAccount", key: 'currentAccount',
header: "Cari Hesap", header: 'Cari Hesap',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div> <div>
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">
{waybill.currentAccount?.accountCode || "Bilinmeyen"} {waybill.currentAccount?.accountCode || 'Bilinmeyen'}
</div>
<div className="text-sm text-gray-500">
{waybill.currentAccount?.accountCode}
</div> </div>
<div className="text-sm text-gray-500">{waybill.currentAccount?.accountCode}</div>
</div> </div>
), ),
}, },
{ {
key: "dates", key: 'dates',
header: "Tarihler", header: 'Tarihler',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div className="text-sm"> <div className="text-sm">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
@ -183,27 +155,23 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
), ),
}, },
{ {
key: "amounts", key: 'amounts',
header: "Tutarlar", header: 'Tutarlar',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div className="text-right"> <div className="text-right">
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">{formatCurrency(waybill.totalAmount)}</div>
{formatCurrency(waybill.totalAmount)} <div className="text-sm text-gray-500">{waybill.items.length} kalem</div>
</div>
<div className="text-sm text-gray-500">
{waybill.items.length} kalem
</div>
</div> </div>
), ),
}, },
{ {
key: "status", key: 'status',
header: "Durum", header: 'Durum',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div className="space-y-1"> <div className="space-y-1">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
waybill.status waybill.status,
)}`} )}`}
> >
{getWaybillStatusText(waybill.status)} {getWaybillStatusText(waybill.status)}
@ -211,25 +179,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<br /> <br />
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${ className={`px-2 py-1 text-xs font-medium rounded-full ${
waybill.isInvoiced waybill.isInvoiced ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
? "bg-green-100 text-green-800"
: "bg-yellow-100 text-yellow-800"
}`} }`}
> >
{waybill.isInvoiced ? "Faturalandı" : "Faturalanmadı"} {waybill.isInvoiced ? 'Faturalandı' : 'Faturalanmadı'}
</span> </span>
</div> </div>
), ),
}, },
{ {
key: "carrier", key: 'carrier',
header: "Kargo", header: 'Kargo',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div className="text-sm"> <div className="text-sm">
{waybill.carrierCompany && ( {waybill.carrierCompany && (
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">{waybill.carrierCompany}</div>
{waybill.carrierCompany}
</div>
)} )}
{waybill.receiverName && ( {waybill.receiverName && (
<div className="text-gray-500">Alıcı: {waybill.receiverName}</div> <div className="text-gray-500">Alıcı: {waybill.receiverName}</div>
@ -238,8 +202,8 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
), ),
}, },
{ {
key: "actions", key: 'actions',
header: "İşlemler", header: 'İşlemler',
render: (waybill: FiWaybill) => ( render: (waybill: FiWaybill) => (
<div className="flex gap-1"> <div className="flex gap-1">
<button <button
@ -256,16 +220,15 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
> >
<FaEdit className="w-4 h-4" /> <FaEdit className="w-4 h-4" />
</button> </button>
{!waybill.isInvoiced && {!waybill.isInvoiced && waybill.status === WaybillStatusEnum.Delivered && (
waybill.status === WaybillStatusEnum.Delivered && ( <button
<button onClick={() => onCreateInvoice(waybill)}
onClick={() => onCreateInvoice(waybill)} className="p-1 text-purple-600 hover:bg-purple-50 rounded"
className="p-1 text-purple-600 hover:bg-purple-50 rounded" title="Fatura Oluştur"
title="Fatura Oluştur" >
> <FaFileAlt className="w-4 h-4" />
<FaFileAlt className="w-4 h-4" /> </button>
</button> )}
)}
{waybill.status === WaybillStatusEnum.Confirmed && ( {waybill.status === WaybillStatusEnum.Confirmed && (
<button <button
onClick={() => onMarkAsDelivered(waybill)} onClick={() => onMarkAsDelivered(waybill)}
@ -278,18 +241,13 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
</div> </div>
), ),
}, },
]; ]
// Calculate statistics // Calculate statistics
const totalWaybills = waybills.length; const totalWaybills = waybills.length
const notInvoicedWaybills = waybills.filter((w) => !w.isInvoiced); const notInvoicedWaybills = waybills.filter((w) => !w.isInvoiced)
const deliveredWaybills = waybills.filter( const deliveredWaybills = waybills.filter((w) => w.status === WaybillStatusEnum.Delivered)
(w) => w.status === WaybillStatusEnum.Delivered const totalNotInvoicedAmount = notInvoicedWaybills.reduce((sum, w) => sum + w.totalAmount, 0)
);
const totalNotInvoicedAmount = notInvoicedWaybills.reduce(
(sum, w) => sum + w.totalAmount,
0
);
// Waybill type distribution // Waybill type distribution
const typeDistribution = Object.values(WaybillTypeEnum).map((type) => ({ const typeDistribution = Object.values(WaybillTypeEnum).map((type) => ({
@ -298,16 +256,14 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
amount: waybills amount: waybills
.filter((w) => w.waybillType === type) .filter((w) => w.waybillType === type)
.reduce((sum, w) => sum + w.totalAmount, 0), .reduce((sum, w) => sum + w.totalAmount, 0),
})); }))
// Status distribution // Status distribution
const statusDistribution = Object.values(WaybillStatusEnum).map((status) => ({ const statusDistribution = Object.values(WaybillStatusEnum).map((status) => ({
status, status,
count: waybills.filter((w) => w.status === status).length, count: waybills.filter((w) => w.status === status).length,
amount: waybills amount: waybills.filter((w) => w.status === status).reduce((sum, w) => sum + w.totalAmount, 0),
.filter((w) => w.status === status) }))
.reduce((sum, w) => sum + w.totalAmount, 0),
}));
return ( return (
<div className="space-y-2"> <div className="space-y-2">
@ -315,9 +271,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<h2 className="text-2xl font-bold text-gray-900">İrsaliye Yönetimi</h2> <h2 className="text-2xl font-bold text-gray-900">İrsaliye Yönetimi</h2>
<p className="text-gray-600"> <p className="text-gray-600">Giriş ve çıkış irsaliyeleri yönetimi</p>
Giriş ve çıkış irsaliyeleri yönetimi
</p>
</div> </div>
<div className="flex gap-2 text-sm"> <div className="flex gap-2 text-sm">
<button <button
@ -332,12 +286,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
{/* Stats Cards */} {/* Stats Cards */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4"> <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<Widget <Widget title="Toplam İrsaliye" value={totalWaybills} color="blue" icon="FaFileAlt" />
title="Toplam İrsaliye"
value={totalWaybills}
color="blue"
icon="FaFileAlt"
/>
<Widget <Widget
title="Faturalanmamış" title="Faturalanmamış"
@ -364,25 +313,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
{/* Distribution Charts */} {/* Distribution Charts */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-white rounded-lg shadow-sm border p-4"> <div className="bg-white rounded-lg shadow-sm border p-4">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">İrsaliye Türü Dağılımı</h3>
İrsaliye Türü Dağılımı
</h3>
<div className="space-y-2"> <div className="space-y-2">
{typeDistribution.map(({ type, count, amount }) => ( {typeDistribution.map(({ type, count, amount }) => (
<div key={type} className="flex items-center justify-between"> <div key={type} className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
type type,
)}`} )}`}
> >
{getWaybillTypeText(type)} {getWaybillTypeText(type)}
</span> </span>
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<span className="text-sm text-gray-600"> <span className="text-sm text-gray-600">{count} irsaliye</span>
{count} irsaliye
</span>
<span className="text-sm font-medium text-gray-900"> <span className="text-sm font-medium text-gray-900">
{formatCurrency(amount)} {formatCurrency(amount)}
</span> </span>
@ -393,25 +338,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
</div> </div>
<div className="bg-white rounded-lg shadow-sm border p-4"> <div className="bg-white rounded-lg shadow-sm border p-4">
<h3 className="text-base font-semibold text-gray-900 mb-3"> <h3 className="text-base font-semibold text-gray-900 mb-3">Durum Dağılımı</h3>
Durum Dağılımı
</h3>
<div className="space-y-2"> <div className="space-y-2">
{statusDistribution.map(({ status, count, amount }) => ( {statusDistribution.map(({ status, count, amount }) => (
<div key={status} className="flex items-center justify-between"> <div key={status} className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span <span
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor( className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
status status,
)}`} )}`}
> >
{getWaybillStatusText(status)} {getWaybillStatusText(status)}
</span> </span>
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<span className="text-sm text-gray-600"> <span className="text-sm text-gray-600">{count} irsaliye</span>
{count} irsaliye
</span>
<span className="text-sm font-medium text-gray-900"> <span className="text-sm font-medium text-gray-900">
{formatCurrency(amount)} {formatCurrency(amount)}
</span> </span>
@ -427,13 +368,11 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<div className="bg-orange-50 border border-orange-200 rounded-lg p-3"> <div className="bg-orange-50 border border-orange-200 rounded-lg p-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<FaExclamationTriangle className="w-5 h-5 text-orange-600" /> <FaExclamationTriangle className="w-5 h-5 text-orange-600" />
<h3 className="text-base font-semibold text-orange-900"> <h3 className="text-base font-semibold text-orange-900">Faturalanmamış İrsaliyeler</h3>
Faturalanmamış İrsaliyeler
</h3>
</div> </div>
<p className="text-sm text-orange-700 mt-1"> <p className="text-sm text-orange-700 mt-1">
{notInvoicedWaybills.length} adet irsaliye henüz faturalanmamış. {notInvoicedWaybills.length} adet irsaliye henüz faturalanmamış. Toplam tutar:{' '}
Toplam tutar: {formatCurrency(totalNotInvoicedAmount)} {formatCurrency(totalNotInvoicedAmount)}
</p> </p>
</div> </div>
)} )}
@ -453,9 +392,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<select <select
value={selectedType} value={selectedType}
onChange={(e) => onChange={(e) => setSelectedType(e.target.value as WaybillTypeEnum | 'all')}
setSelectedType(e.target.value as WaybillTypeEnum | "all")
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Türler</option> <option value="all">Tüm Türler</option>
@ -468,9 +405,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<select <select
value={selectedStatus} value={selectedStatus}
onChange={(e) => onChange={(e) => setSelectedStatus(e.target.value as WaybillStatusEnum | 'all')}
setSelectedStatus(e.target.value as WaybillStatusEnum | "all")
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
@ -484,9 +419,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<select <select
value={showInvoicedOnly} value={showInvoicedOnly}
onChange={(e) => onChange={(e) =>
setShowInvoicedOnly( setShowInvoicedOnly(e.target.value as 'all' | 'invoiced' | 'not_invoiced')
e.target.value as "all" | "invoiced" | "not_invoiced"
)
} }
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
@ -497,9 +430,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
<select <select
value={sortBy} value={sortBy}
onChange={(e) => onChange={(e) => setSortBy(e.target.value as 'date' | 'amount' | 'deliveryDate')}
setSortBy(e.target.value as "date" | "amount" | "deliveryDate")
}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="date">Tarihe Göre</option> <option value="date">Tarihe Göre</option>
@ -516,16 +447,14 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
{filteredWaybills.length === 0 && ( {filteredWaybills.length === 0 && (
<div className="text-center py-10"> <div className="text-center py-10">
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" /> <FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
<h3 className="text-base font-medium text-gray-900 mb-2"> <h3 className="text-base font-medium text-gray-900 mb-2">İrsaliye bulunamadı</h3>
İrsaliye bulunamadı
</h3>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Yeni bir irsaliye ekleyin veya arama kriterlerinizi değiştirin. Yeni bir irsaliye ekleyin veya arama kriterlerinizi değiştirin.
</p> </p>
</div> </div>
)} )}
</div> </div>
); )
}; }
export default WaybillManagement; export default WaybillManagement

View file

@ -28,8 +28,8 @@ import Widget from '../../../components/common/Widget'
import { BusinessPartyStatusEnum, PartyType } from '../../../types/common' import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
import { import {
getBusinessPartyStatusColor, getBusinessPartyStatusColor,
getBusinessPartyStatusName, getBusinessPartyStatusText,
getCustomerSegmentName, getCustomerSegmentText,
} from '../../../utils/erp' } from '../../../utils/erp'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
@ -177,10 +177,11 @@ const CustomerCards: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option> {Object.values(BusinessPartyStatusEnum).map((status) => (
<option value={BusinessPartyStatusEnum.Active}>Aktif</option> <option key={status} value={status}>
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option> {getBusinessPartyStatusText(status)}
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option> </option>
))}
</select> </select>
</div> </div>
@ -192,10 +193,11 @@ const CustomerCards: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option> {Object.values(CustomerSegmentEnum).map((segment) => (
<option value={CustomerSegmentEnum.SMB}>KOBİ</option> <option key={segment} value={segment}>
<option value={CustomerSegmentEnum.Startup}>Girişim</option> {getCustomerSegmentText(segment)}
<option value={CustomerSegmentEnum.Government}>Kamu</option> </option>
))}
</select> </select>
</div> </div>
@ -289,7 +291,7 @@ const CustomerCards: React.FC = () => {
{customer.code} {customer.code}
</h3> </h3>
<p className="text-sm text-gray-600"> <p className="text-sm text-gray-600">
{getCustomerSegmentName(customer.customerSegment!)} {getCustomerSegmentText(customer.customerSegment!)}
</p> </p>
</div> </div>
</div> </div>
@ -299,7 +301,7 @@ const CustomerCards: React.FC = () => {
getBusinessPartyStatusColor(customer.status!), getBusinessPartyStatusColor(customer.status!),
)} )}
> >
{getBusinessPartyStatusName(customer.status!)} {getBusinessPartyStatusText(customer.status!)}
</span> </span>
</div> </div>

View file

@ -18,6 +18,13 @@ import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBu
import { BusinessParty, BusinessPartyStatusEnum, PaymentTerms } from '../../../types/common' import { BusinessParty, BusinessPartyStatusEnum, PaymentTerms } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import {
getBusinessPartyStatusText,
getCustomerSegmentText,
getCustomerTypeText,
getPaymentTermsText,
} from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
const CustomerEdit: React.FC = () => { const CustomerEdit: React.FC = () => {
const { id } = useParams<{ id: string }>() const { id } = useParams<{ id: string }>()
@ -316,10 +323,11 @@ const CustomerEdit: React.FC = () => {
onChange={(e) => handleInputChange('customerType', e.target.value)} onChange={(e) => handleInputChange('customerType', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value={CustomerTypeEnum.Company}>Şirket</option> {Object.values(CustomerTypeEnum).map((type) => (
<option value={CustomerTypeEnum.Individual}>Bireysel</option> <option key={type} value={type}>
<option value={CustomerTypeEnum.Government}>Kamu</option> {getCustomerTypeText(type)}
<option value={CustomerTypeEnum.NonProfit}>Kar Amacı Gütmeyen</option> </option>
))}
</select> </select>
</div> </div>
@ -354,10 +362,11 @@ const CustomerEdit: React.FC = () => {
onChange={(e) => handleInputChange('status', e.target.value)} onChange={(e) => handleInputChange('status', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option> {Object.values(BusinessPartyStatusEnum).map((status) => (
<option value={BusinessPartyStatusEnum.Active}>Aktif</option> <option key={status} value={status}>
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option> {getBusinessPartyStatusText(status)}
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option> </option>
))}
</select> </select>
</div> </div>
@ -370,10 +379,11 @@ const CustomerEdit: React.FC = () => {
onChange={(e) => handleInputChange('customerSegment', e.target.value)} onChange={(e) => handleInputChange('customerSegment', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option> {Object.values(CustomerSegmentEnum).map((segment) => (
<option value={CustomerSegmentEnum.SMB}>KOBİ</option> <option key={segment} value={segment}>
<option value={CustomerSegmentEnum.Startup}>Girişim</option> {getCustomerSegmentText(segment)}
<option value={CustomerSegmentEnum.Government}>Kamu</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -644,10 +654,11 @@ const CustomerEdit: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="TRY">Türk Lirası (TRY)</option> {mockCurrencies.map((currency) => (
<option value="USD">Amerikan Doları (USD)</option> <option key={currency.value} value={currency.value}>
<option value="EUR">Euro (EUR)</option> {currency.value} - {currency.label}
<option value="GBP">İngiliz Sterlini (GBP)</option> </option>
))}
</select> </select>
</div> </div>
@ -660,11 +671,11 @@ const CustomerEdit: React.FC = () => {
onChange={(e) => handleInputChange('paymentTerms', e.target.value)} onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value={PaymentTerms.Prepaid}>Peşin</option> {Object.values(PaymentTerms).map((term) => (
<option value={PaymentTerms.COD}>Kapıda Ödeme</option> <option key={term} value={term}>
<option value={PaymentTerms.Net30}>30 Gün Vade</option> {getPaymentTermsText(term)}
<option value={PaymentTerms.Net60}>60 Gün Vade</option> </option>
<option value={PaymentTerms.Net90}>90 Gün Vade</option> ))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -11,9 +11,23 @@ import {
} from 'react-icons/fa' } from 'react-icons/fa'
import LoadingSpinner from '../../../components/common/LoadingSpinner' import LoadingSpinner from '../../../components/common/LoadingSpinner'
import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBusinessParties' import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBusinessParties'
import { BusinessParty } from '../../../types/common' import {
BusinessParty,
BusinessPartyIndustryEnum,
BusinessPartyStatusEnum,
PaymentTerms,
} from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { mockCurrencies } from '@/mocks/mockCurrencies'
import {
getBusinessPartyIndustryText,
getBusinessPartyStatusText,
getCustomerSegmentText,
getCustomerTypeText,
getPaymentTermsText,
} from '@/utils/erp'
import { CustomerSegmentEnum, CustomerTypeEnum } from '@/types/crm'
interface ValidationErrors { interface ValidationErrors {
[key: string]: string [key: string]: string
@ -181,8 +195,11 @@ const CustomerForm: React.FC = () => {
} }
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="COMPANY">Şirket</option> {Object.values(CustomerTypeEnum).map((type) => (
<option value="INDIVIDUAL">Bireysel</option> <option key={type} value={type}>
{getCustomerTypeText(type)}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -216,14 +233,11 @@ const CustomerForm: React.FC = () => {
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="">Sektör seçin</option> <option value="">Sektör seçin</option>
<option value="TECHNOLOGY">Teknoloji</option> {Object.values(BusinessPartyIndustryEnum).map((industry) => (
<option value="MANUFACTURING">İmalat</option> <option key={industry} value={industry}>
<option value="CONSTRUCTION">İnşaat</option> {getBusinessPartyIndustryText(industry)}
<option value="AUTOMOTIVE">Otomotiv</option> </option>
<option value="RETAIL">Perakende</option> ))}
<option value="FINANCE">Finans</option>
<option value="HEALTHCARE">Sağlık</option>
<option value="OTHER">Diğer</option>
</select> </select>
</div> </div>
</div> </div>
@ -369,11 +383,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('paymentTerms', e.target.value)} onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="CASH">Peşin</option> {Object.values(PaymentTerms).map((term) => (
<option value="NET_15">15 Gün Vadeli</option> <option key={term} value={term}>
<option value="NET_30">30 Gün Vadeli</option> {getPaymentTermsText(term)}
<option value="NET_60">60 Gün Vadeli</option> </option>
<option value="NET_90">90 Gün Vadeli</option> ))}
</select> </select>
</div> </div>
@ -386,9 +400,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="TRY">Türk Lirası (TRY)</option> {mockCurrencies.map((currency) => (
<option value="USD">Amerikan Doları (USD)</option> <option key={currency.value} value={currency.value}>
<option value="EUR">Euro (EUR)</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -415,10 +431,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('status', e.target.value)} onChange={(e) => handleInputChange('status', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="ACTIVE">Aktif</option> {Object.values(BusinessPartyStatusEnum).map((status) => (
<option value="INACTIVE">Pasif</option> <option key={status} value={status}>
<option value="PROSPECT">Potansiyel</option> {getBusinessPartyStatusText(status)}
<option value="BLOCKED">Blokeli</option> </option>
))}
</select> </select>
</div> </div>
@ -431,10 +448,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('customerSegment', e.target.value)} onChange={(e) => handleInputChange('customerSegment', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="STANDARD">Standart</option> {Object.values(CustomerSegmentEnum).map((segment) => (
<option value="PREMIUM">Premium</option> <option key={segment} value={segment}>
<option value="ENTERPRISE">Kurumsal</option> {getCustomerSegmentText(segment)}
<option value="VIP">VIP</option> </option>
))}
</select> </select>
</div> </div>
@ -442,16 +460,13 @@ const CustomerForm: React.FC = () => {
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">
Sorumlu Satış Temsilcisi Sorumlu Satış Temsilcisi
</label> </label>
<select <input
type="text"
value={formData.assignedSalesRep} value={formData.assignedSalesRep}
onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)} onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> placeholder="Satış temsilcisi adı"
<option value="">Temsilci seçin</option> />
<option value="sales_rep_1">Mehmet Özkan</option>
<option value="sales_rep_2">Ayşe Demir</option>
<option value="sales_rep_3">Ali Yılmaz</option>
</select>
</div> </div>
</div> </div>

View file

@ -10,10 +10,24 @@ import {
FaEnvelope, FaEnvelope,
} from 'react-icons/fa' } from 'react-icons/fa'
import LoadingSpinner from '../../../components/common/LoadingSpinner' import LoadingSpinner from '../../../components/common/LoadingSpinner'
import { BusinessParty } from '../../../types/common' import {
BusinessParty,
BusinessPartyIndustryEnum,
BusinessPartyStatusEnum,
PaymentTerms,
} from '../../../types/common'
import { mockBusinessPartyNew } from '../../../mocks/mockBusinessParties' import { mockBusinessPartyNew } from '../../../mocks/mockBusinessParties'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { mockCurrencies } from '@/mocks/mockCurrencies'
import { CustomerSegmentEnum, CustomerTypeEnum } from '@/types/crm'
import {
getBusinessPartyIndustryText,
getBusinessPartyStatusText,
getCustomerSegmentText,
getCustomerTypeText,
getPaymentTermsText,
} from '@/utils/erp'
interface ValidationErrors { interface ValidationErrors {
[key: string]: string [key: string]: string
@ -174,13 +188,14 @@ const CustomerForm: React.FC = () => {
</label> </label>
<select <select
value={formData.customerType} value={formData.customerType}
onChange={(e) => onChange={(e) => handleInputChange('customerType', e.target.value)}
handleInputChange('customerType', e.target.value as 'INDIVIDUAL' | 'COMPANY')
}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="COMPANY">Şirket</option> {Object.values(CustomerTypeEnum).map((type) => (
<option value="INDIVIDUAL">Bireysel</option> <option key={type} value={type}>
{getCustomerTypeText(type)}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -214,14 +229,11 @@ const CustomerForm: React.FC = () => {
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="">Sektör seçin</option> <option value="">Sektör seçin</option>
<option value="TECHNOLOGY">Teknoloji</option> {Object.values(BusinessPartyIndustryEnum).map((industry) => (
<option value="MANUFACTURING">İmalat</option> <option key={industry} value={industry}>
<option value="CONSTRUCTION">İnşaat</option> {getBusinessPartyIndustryText(industry)}
<option value="AUTOMOTIVE">Otomotiv</option> </option>
<option value="RETAIL">Perakende</option> ))}
<option value="FINANCE">Finans</option>
<option value="HEALTHCARE">Sağlık</option>
<option value="OTHER">Diğer</option>
</select> </select>
</div> </div>
</div> </div>
@ -367,11 +379,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('paymentTerms', e.target.value)} onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="CASH">Peşin</option> {Object.values(PaymentTerms).map((term) => (
<option value="NET_15">15 Gün Vadeli</option> <option key={term} value={term}>
<option value="NET_30">30 Gün Vadeli</option> {getPaymentTermsText(term)}
<option value="NET_60">60 Gün Vadeli</option> </option>
<option value="NET_90">90 Gün Vadeli</option> ))}
</select> </select>
</div> </div>
@ -384,9 +396,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="TRY">Türk Lirası (TRY)</option> {mockCurrencies.map((currency) => (
<option value="USD">Amerikan Doları (USD)</option> <option key={currency.value} value={currency.value}>
<option value="EUR">Euro (EUR)</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -413,10 +427,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('status', e.target.value)} onChange={(e) => handleInputChange('status', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="ACTIVE">Aktif</option> {Object.values(BusinessPartyStatusEnum).map((status) => (
<option value="INACTIVE">Pasif</option> <option key={status} value={status}>
<option value="PROSPECT">Potansiyel</option> {getBusinessPartyStatusText(status)}
<option value="BLOCKED">Blokeli</option> </option>
))}
</select> </select>
</div> </div>
@ -429,10 +444,11 @@ const CustomerForm: React.FC = () => {
onChange={(e) => handleInputChange('customerSegment', e.target.value)} onChange={(e) => handleInputChange('customerSegment', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="STANDARD">Standart</option> {Object.values(CustomerSegmentEnum).map((segment) => (
<option value="PREMIUM">Premium</option> <option key={segment} value={segment}>
<option value="ENTERPRISE">Kurumsal</option> {getCustomerSegmentText(segment)}
<option value="VIP">VIP</option> </option>
))}
</select> </select>
</div> </div>
@ -440,16 +456,13 @@ const CustomerForm: React.FC = () => {
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">
Sorumlu Satış Temsilcisi Sorumlu Satış Temsilcisi
</label> </label>
<select <input
type="text"
value={formData.assignedSalesRep} value={formData.assignedSalesRep}
onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)} onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)}
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> placeholder="Satış temsilcisi adı"
<option value="">Temsilci seçin</option> />
<option value="sales_rep_1">Mehmet Özkan</option>
<option value="sales_rep_2">Ayşe Demir</option>
<option value="sales_rep_3">Ali Yılmaz</option>
</select>
</div> </div>
</div> </div>

View file

@ -25,9 +25,9 @@ import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
import Widget from '../../../components/common/Widget' import Widget from '../../../components/common/Widget'
import { import {
getBusinessPartyStatusColor, getBusinessPartyStatusColor,
getBusinessPartyStatusName, getBusinessPartyStatusText,
getCustomerSegmentColor, getCustomerSegmentColor,
getCustomerSegmentName, getCustomerSegmentText,
} from '../../../utils/erp' } from '../../../utils/erp'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
@ -146,10 +146,11 @@ const CustomerList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option> {Object.values(BusinessPartyStatusEnum).map((status) => (
<option value={BusinessPartyStatusEnum.Active}>Aktif</option> <option key={status} value={status}>
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option> {getBusinessPartyStatusText(status)}
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option> </option>
))}
</select> </select>
</div> </div>
@ -161,10 +162,11 @@ const CustomerList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option> {Object.values(CustomerSegmentEnum).map((segment) => (
<option value={CustomerSegmentEnum.SMB}>KOBİ</option> <option key={segment} value={segment}>
<option value={CustomerSegmentEnum.Startup}>Girişim</option> {getCustomerSegmentText(segment)}
<option value={CustomerSegmentEnum.Government}>Kamu</option> </option>
))}
</select> </select>
</div> </div>
@ -310,7 +312,7 @@ const CustomerList: React.FC = () => {
), ),
)} )}
> >
{getCustomerSegmentName( {getCustomerSegmentText(
customer.customerSegment || CustomerSegmentEnum.SMB, customer.customerSegment || CustomerSegmentEnum.SMB,
)} )}
</div> </div>
@ -322,7 +324,7 @@ const CustomerList: React.FC = () => {
), ),
)} )}
> >
{getBusinessPartyStatusName( {getBusinessPartyStatusText(
customer.status ?? BusinessPartyStatusEnum.Prospect, customer.status ?? BusinessPartyStatusEnum.Prospect,
)} )}
</span> </span>

View file

@ -30,8 +30,8 @@ import dayjs from 'dayjs'
import { mockBusinessParties } from '../../../mocks/mockBusinessParties' import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
import { import {
getBusinessPartyStatusColor, getBusinessPartyStatusColor,
getBusinessPartyStatusName, getBusinessPartyStatusText,
getCustomerSegmentName, getCustomerSegmentText,
} from '../../../utils/erp' } from '../../../utils/erp'
import { BusinessPartyStatusEnum } from '../../../types/common' import { BusinessPartyStatusEnum } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
@ -167,7 +167,7 @@ const CustomerView: React.FC = () => {
), ),
)} )}
> >
{getBusinessPartyStatusName( {getBusinessPartyStatusText(
customer.status || BusinessPartyStatusEnum.Active, customer.status || BusinessPartyStatusEnum.Active,
)} )}
</span> </span>
@ -176,7 +176,7 @@ const CustomerView: React.FC = () => {
<span className="text-sm text-gray-600">{customer.code}</span> <span className="text-sm text-gray-600">{customer.code}</span>
<span className="text-sm text-gray-400"></span> <span className="text-sm text-gray-400"></span>
<span className="text-sm text-gray-600"> <span className="text-sm text-gray-600">
{getCustomerSegmentName( {getCustomerSegmentText(
customer.customerSegment || CustomerSegmentEnum.Startup, customer.customerSegment || CustomerSegmentEnum.Startup,
)} )}
</span> </span>
@ -311,7 +311,7 @@ const CustomerView: React.FC = () => {
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-gray-600">Segment:</span> <span className="text-gray-600">Segment:</span>
<span className="font-medium"> <span className="font-medium">
{getCustomerSegmentName( {getCustomerSegmentText(
customer.customerSegment || CustomerSegmentEnum.Startup, customer.customerSegment || CustomerSegmentEnum.Startup,
)} )}
</span> </span>
@ -729,7 +729,7 @@ const CustomerView: React.FC = () => {
), ),
)} )}
> >
{getBusinessPartyStatusName( {getBusinessPartyStatusText(
customer.status || BusinessPartyStatusEnum.Active, customer.status || BusinessPartyStatusEnum.Active,
)} )}
</span> </span>
@ -739,7 +739,7 @@ const CustomerView: React.FC = () => {
Müşteri Segmenti Müşteri Segmenti
</label> </label>
<p className="text-gray-900"> <p className="text-gray-900">
{getCustomerSegmentName( {getCustomerSegmentText(
customer.customerSegment || CustomerSegmentEnum.Startup, customer.customerSegment || CustomerSegmentEnum.Startup,
)} )}
</p> </p>

View file

@ -10,6 +10,7 @@ import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { BusinessParty } from '../../../types/common' import { BusinessParty } from '../../../types/common'
import { getOpportunityLeadSourceText, getOpportunityStageText } from '@/utils/erp' import { getOpportunityLeadSourceText, getOpportunityStageText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
interface OpportunityFormProps { interface OpportunityFormProps {
isOpen: boolean isOpen: boolean
@ -353,9 +354,11 @@ const OpportunityForm: React.FC<OpportunityFormProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY - Türk Lirası</option> {mockCurrencies.map((currency) => (
<option value="USD">USD - Amerikan Doları</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR - Euro</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>

View file

@ -24,6 +24,8 @@ import { mockSalesOrders } from '../../../mocks/mockSalesOrders'
import { BusinessParty, PaymentTerms } from '../../../types/common' import { BusinessParty, PaymentTerms } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { getPaymentTermsText, getSaleOrderStatusText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
const SalesOrderForm: React.FC = () => { const SalesOrderForm: React.FC = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -328,13 +330,11 @@ const SalesOrderForm: React.FC = () => {
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={SaleOrderStatusEnum.Draft}>Taslak</option> {Object.values(SaleOrderStatusEnum).map((status) => (
<option value={SaleOrderStatusEnum.Confirmed}>Onaylandı</option> <option key={status} value={status}>
<option value={SaleOrderStatusEnum.InProduction}>Üretimde</option> {getSaleOrderStatusText(status)}
<option value={SaleOrderStatusEnum.Ready}>Hazır</option> </option>
<option value={SaleOrderStatusEnum.Shipped}>Kargoda</option> ))}
<option value={SaleOrderStatusEnum.Delivered}>Teslim Edildi</option>
<option value={SaleOrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>
</div> </div>
@ -684,9 +684,11 @@ const SalesOrderForm: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY - Türk Lirası</option> {mockCurrencies.map((currency) => (
<option value="USD">USD - ABD Doları</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR - Euro</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
@ -746,11 +748,11 @@ const SalesOrderForm: React.FC = () => {
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Seçin...</option> <option value="">Seçin...</option>
<option value="NET30">30 Gün Vadeli</option> {Object.values(PaymentTerms).map((term) => (
<option value="NET60">60 Gün Vadeli</option> <option key={term} value={term}>
<option value="NET90">90 Gün Vadeli</option> {getPaymentTermsText(term)}
<option value="COD">Kapıda Ödeme</option> </option>
<option value="PREPAID">Peşin</option> ))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -14,6 +14,7 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common' import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { getTeamRoleText } from '@/utils/erp'
const SalesTeamCreate: React.FC = () => { const SalesTeamCreate: React.FC = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -308,9 +309,11 @@ const SalesTeamCreate: React.FC = () => {
onChange={(e) => updateMember(index, 'role', e.target.value)} onChange={(e) => updateMember(index, 'role', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value={TeamRoleEnum.Member}>Üye</option> {Object.values(TeamRoleEnum).map((role) => (
<option value={TeamRoleEnum.Lead}>Takım Lideri</option> <option key={role} value={role}>
<option value={TeamRoleEnum.Manager}>Yönetici</option> {getTeamRoleText(role)}
</option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -15,6 +15,7 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common' import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { getTeamRoleText } from '@/utils/erp'
const SalesTeamEdit: React.FC = () => { const SalesTeamEdit: React.FC = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -358,9 +359,11 @@ const SalesTeamEdit: React.FC = () => {
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value={TeamRoleEnum.Member}>Üye</option> {Object.values(TeamRoleEnum).map((role) => (
<option value={TeamRoleEnum.Lead}>Takım Lideri</option> <option key={role} value={role}>
<option value={TeamRoleEnum.Manager}>Yönetici</option> {getTeamRoleText(role)}
</option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -323,7 +323,7 @@ export function ForumView({
: 'hover:text-blue-600 cursor-pointer' : 'hover:text-blue-600 cursor-pointer'
}`} }`}
> >
Forum <h2 className="text-2xl font-bold text-gray-900">Forum</h2>
</button> </button>
{selectedCategory && ( {selectedCategory && (
<> <>

View file

@ -1,16 +1,17 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaSave, FaTimes } from "react-icons/fa"; import { FaSave, FaTimes } from 'react-icons/fa'
import { HrCostCenter, CostCenterType } from "../../../types/hr"; import { HrCostCenter, CostCenterType } from '../../../types/hr'
import { mockEmployees } from "../../../mocks/mockEmployees"; import { mockEmployees } from '../../../mocks/mockEmployees'
import { mockCostCenters } from "../../../mocks/mockCostCenters"; import { mockCostCenters } from '../../../mocks/mockCostCenters'
import { getCostCenterTypeText } from "../../../utils/erp"; import { getCostCenterTypeText } from '../../../utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
interface CostCenterFormModalProps { interface CostCenterFormModalProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: (costCenter: Partial<HrCostCenter>) => void; onSave: (costCenter: Partial<HrCostCenter>) => void
costCenter?: HrCostCenter; costCenter?: HrCostCenter
title: string; title: string
} }
const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
@ -21,55 +22,55 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
title, title,
}) => { }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
costCenterCode: "", costCenterCode: '',
name: "", name: '',
description: "", description: '',
costCenterType: CostCenterType.Standard, costCenterType: CostCenterType.Standard,
responsibleEmployeeId: "", responsibleEmployeeId: '',
parentCostCenterId: "", parentCostCenterId: '',
budgetedAmount: 0, budgetedAmount: 0,
actualAmount: 0, actualAmount: 0,
currency: "TRY", currency: 'TRY',
fiscalYear: "2025", fiscalYear: '2025',
isActive: true, isActive: true,
}); })
useEffect(() => { useEffect(() => {
if (costCenter) { if (costCenter) {
setFormData({ setFormData({
costCenterCode: costCenter.code, costCenterCode: costCenter.code,
name: costCenter.name, name: costCenter.name,
description: costCenter.description || "", description: costCenter.description || '',
costCenterType: costCenter.costCenterType, costCenterType: costCenter.costCenterType,
responsibleEmployeeId: costCenter.responsibleEmployeeId || "", responsibleEmployeeId: costCenter.responsibleEmployeeId || '',
parentCostCenterId: costCenter.parentCostCenterId || "", parentCostCenterId: costCenter.parentCostCenterId || '',
budgetedAmount: costCenter.budgetedAmount, budgetedAmount: costCenter.budgetedAmount,
actualAmount: costCenter.actualAmount, actualAmount: costCenter.actualAmount,
currency: costCenter.currency, currency: costCenter.currency,
fiscalYear: costCenter.fiscalYear, fiscalYear: costCenter.fiscalYear,
isActive: costCenter.isActive, isActive: costCenter.isActive,
}); })
} else { } else {
setFormData({ setFormData({
costCenterCode: "", costCenterCode: '',
name: "", name: '',
description: "", description: '',
costCenterType: CostCenterType.Standard, costCenterType: CostCenterType.Standard,
responsibleEmployeeId: "", responsibleEmployeeId: '',
parentCostCenterId: "", parentCostCenterId: '',
budgetedAmount: 0, budgetedAmount: 0,
actualAmount: 0, actualAmount: 0,
currency: "TRY", currency: 'TRY',
fiscalYear: "2025", fiscalYear: '2025',
isActive: true, isActive: true,
}); })
} }
}, [costCenter]); }, [costCenter])
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
onSave(formData); onSave(formData)
}; }
return ( return (
isOpen && ( isOpen && (
@ -77,10 +78,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
<div className="bg-white rounded-lg p-3 w-full max-w-lg max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg p-3 w-full max-w-lg max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<h2 className="text-base font-bold text-gray-900">{title}</h2> <h2 className="text-base font-bold text-gray-900">{title}</h2>
<button <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
onClick={onClose}
className="text-gray-400 hover:text-gray-600"
>
<FaTimes className="w-5 h-5" /> <FaTimes className="w-5 h-5" />
</button> </button>
</div> </div>
@ -94,9 +92,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
<input <input
type="text" type="text"
value={formData.costCenterCode} value={formData.costCenterCode}
onChange={(e) => onChange={(e) => setFormData({ ...formData, costCenterCode: e.target.value })}
setFormData({ ...formData, costCenterCode: e.target.value })
}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required required
/> />
@ -109,9 +105,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
<input <input
type="text" type="text"
value={formData.name} value={formData.name}
onChange={(e) => onChange={(e) => setFormData({ ...formData, name: e.target.value })}
setFormData({ ...formData, name: e.target.value })
}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required required
/> />
@ -119,14 +113,10 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">ıklama</label>
ıklama
</label>
<textarea <textarea
value={formData.description} value={formData.description}
onChange={(e) => onChange={(e) => setFormData({ ...formData, description: e.target.value })}
setFormData({ ...formData, description: e.target.value })
}
rows={2} rows={2}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
@ -206,15 +196,11 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Mali Yıl</label>
Mali Yıl
</label>
<input <input
type="text" type="text"
value={formData.fiscalYear} value={formData.fiscalYear}
onChange={(e) => onChange={(e) => setFormData({ ...formData, fiscalYear: e.target.value })}
setFormData({ ...formData, fiscalYear: e.target.value })
}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
@ -222,9 +208,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Bütçe Tutarı</label>
Bütçe Tutarı
</label>
<input <input
type="number" type="number"
value={formData.budgetedAmount} value={formData.budgetedAmount}
@ -256,19 +240,17 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Para Birimi</label>
Para Birimi
</label>
<select <select
value={formData.currency} value={formData.currency}
onChange={(e) => onChange={(e) => setFormData({ ...formData, currency: e.target.value })}
setFormData({ ...formData, currency: e.target.value })
}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -277,9 +259,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
<input <input
type="checkbox" type="checkbox"
checked={formData.isActive} checked={formData.isActive}
onChange={(e) => onChange={(e) => setFormData({ ...formData, isActive: e.target.checked })}
setFormData({ ...formData, isActive: e.target.checked })
}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/> />
<label className="ml-2 block text-sm text-gray-900">Aktif</label> <label className="ml-2 block text-sm text-gray-900">Aktif</label>
@ -305,7 +285,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
</div> </div>
</div> </div>
) )
); )
}; }
export default CostCenterFormModal; export default CostCenterFormModal

View file

@ -808,9 +808,11 @@ const Degree360Evaluation: React.FC = () => {
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm" className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={CampaignStatusEnum.Draft}>Taslak</option> {Object.values(CampaignStatusEnum).map((status) => (
<option value={CampaignStatusEnum.Active}>Aktif</option> <option key={status} value={status}>
<option value={CampaignStatusEnum.Completed}>Tamamlandı</option> {getCampaignStatusText(status)}
</option>
))}
</select> </select>
<select <select
@ -834,7 +836,7 @@ const Degree360Evaluation: React.FC = () => {
<option value="all">Tüm Personel</option> <option value="all">Tüm Personel</option>
{mockEmployees.map((employee) => ( {mockEmployees.map((employee) => (
<option key={employee.id} value={employee.id}> <option key={employee.id} value={employee.id}>
{employee.firstName} {employee.lastName} {employee.fullName}
</option> </option>
))} ))}
</select> </select>
@ -887,11 +889,11 @@ const Degree360Evaluation: React.FC = () => {
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm" className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={ParticipantStatusEnum.Invited}>Davet Edildi</option> {Object.values(ParticipantStatusEnum).map((status) => (
<option value={ParticipantStatusEnum.Started}>Başladı</option> <option key={status} value={status}>
<option value={ParticipantStatusEnum.Completed}>Tamamlandı</option> {getParticipantStatusText(status)}
<option value={ParticipantStatusEnum.Expired}>Süresi Dolmuş</option> </option>
<option value={ParticipantStatusEnum.Declined}>Reddedildi</option> ))}
</select> </select>
<select <select

View file

@ -7,6 +7,7 @@ import {
QuestionTypeEnum, QuestionTypeEnum,
HrQuestionOption, HrQuestionOption,
AssessorTypeEnum, AssessorTypeEnum,
getQuestionTypeText,
} from '../../../types/hr' } from '../../../types/hr'
import DataTable, { Column } from '../../../components/common/DataTable' import DataTable, { Column } from '../../../components/common/DataTable'
import { mockEvaluation360Templates } from '../../../mocks/mockEvaluation360Templates' import { mockEvaluation360Templates } from '../../../mocks/mockEvaluation360Templates'
@ -692,10 +693,11 @@ const Degree360Templates: React.FC = () => {
} }
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500" className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
> >
<option value={QuestionTypeEnum.Rating}>Puanlama</option> {Object.values(QuestionTypeEnum).map((type) => (
<option value={QuestionTypeEnum.MultipleChoice}>Çoktan Seçmeli</option> <option key={type} value={type}>
<option value={QuestionTypeEnum.Text}>Metin</option> {getQuestionTypeText(type)}
<option value={QuestionTypeEnum.YesNo}>Evet/Hayır</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -82,11 +82,11 @@ const EmployeeCards: React.FC = () => {
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={EmployeeStatusEnum.Active}>Aktif</option> {Object.values(EmployeeStatusEnum).map((status) => (
<option value={EmployeeStatusEnum.Inactive}>Pasif</option> <option key={status} value={status}>
<option value={EmployeeStatusEnum.OnLeave}>İzinli</option> {getEmployeeStatusText(status)}
<option value={EmployeeStatusEnum.Suspended}>Askıda</option> </option>
<option value={EmployeeStatusEnum.Terminated}>İşten Çıkarılmış</option> ))}
</select> </select>
</div> </div>

View file

@ -26,6 +26,15 @@ import {
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { mockCurrencies } from '@/mocks/mockCurrencies'
import {
getEmployeeStatusText,
getEmploymentTypeText,
getFrequencyUnitText,
getGenderText,
getMaritalStatusText,
} from '@/utils/erp'
import { FrequencyUnitEnum } from '@/types/pm'
interface ValidationErrors { interface ValidationErrors {
[key: string]: string [key: string]: string
@ -370,8 +379,11 @@ const EmployeeForm: React.FC = () => {
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="">Cinsiyet seçin</option> <option value="">Cinsiyet seçin</option>
<option value="MALE">Erkek</option> {Object.values(GenderEnum).map((gender) => (
<option value="FEMALE">Kadın</option> <option key={gender} value={gender}>
{getGenderText(gender)}
</option>
))}
</select> </select>
</div> </div>
@ -385,10 +397,11 @@ const EmployeeForm: React.FC = () => {
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="">Medeni durum seçin</option> <option value="">Medeni durum seçin</option>
<option value="SINGLE">Bekar</option> {Object.values(MaritalStatusEnum).map((status) => (
<option value="MARRIED">Evli</option> <option key={status} value={status}>
<option value="DIVORCED">Boşanmış</option> {getMaritalStatusText(status)}
<option value="WIDOWED">Dul</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -508,11 +521,11 @@ const EmployeeForm: React.FC = () => {
}`} }`}
> >
<option value="">Tip seçin</option> <option value="">Tip seçin</option>
<option value="FULL_TIME">Tam Zamanlı</option> {Object.values(EmploymentTypeEnum).map((type) => (
<option value="PART_TIME">Yarı Zamanlı</option> <option key={type} value={type}>
<option value="CONTRACT">Sözleşmeli</option> {getEmploymentTypeText(type)}
<option value="INTERN">Stajyer</option> </option>
<option value="TEMPORARY">Geçici</option> ))}
</select> </select>
{errors.employmentType && ( {errors.employmentType && (
<p className="mt-1 text-sm text-red-600">{errors.employmentType}</p> <p className="mt-1 text-sm text-red-600">{errors.employmentType}</p>
@ -660,9 +673,11 @@ const EmployeeForm: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="TRY">Türk Lirası (TRY)</option> {mockCurrencies.map((currency) => (
<option value="USD">Amerikan Doları (USD)</option> <option key={currency.value} value={currency.value}>
<option value="EUR">Euro (EUR)</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
@ -676,9 +691,15 @@ const EmployeeForm: React.FC = () => {
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="">Grup seçin</option> <option value="">Grup seçin</option>
<option value="MONTHLY">Aylık</option> <option value={FrequencyUnitEnum.Weeks}>
<option value="WEEKLY">Haftalık</option> {getFrequencyUnitText(FrequencyUnitEnum.Weeks)}
<option value="HOURLY">Saatlik</option> </option>
<option value={FrequencyUnitEnum.Months}>
{getFrequencyUnitText(FrequencyUnitEnum.Months)}
</option>
<option value={FrequencyUnitEnum.Hours}>
{getFrequencyUnitText(FrequencyUnitEnum.Hours)}
</option>
</select> </select>
</div> </div>
</div> </div>
@ -748,10 +769,11 @@ const EmployeeForm: React.FC = () => {
onChange={(e) => handleInputChange('employeeStatus', e.target.value)} onChange={(e) => handleInputChange('employeeStatus', e.target.value)}
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="ACTIVE">Aktif</option> {Object.values(EmployeeStatusEnum).map((status) => (
<option value="INACTIVE">Pasif</option> <option key={status} value={status}>
<option value="ON_LEAVE">İzinli</option> {getEmployeeStatusText(status)}
<option value="TERMINATED">İşten Ayrılmış</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -34,11 +34,12 @@ import {
} from '../../../utils/erp' } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { mockDepartments } from '@/mocks/mockDepartments'
const EmployeeList: React.FC = () => { const EmployeeList: React.FC = () => {
const [searchTerm, setSearchTerm] = useState('') const [searchTerm, setSearchTerm] = useState('')
const [filterStatus, setFilterStatus] = useState('all') const [filterStatus, setFilterStatus] = useState('all')
const [filterDepartment, setFilterDepartment] = useState('all') const [filterDepartment, setFilterDepartment] = useState('')
const [showFilters, setShowFilters] = useState(false) const [showFilters, setShowFilters] = useState(false)
const [viewMode, setViewMode] = useState<'list' | 'cards'>('list') const [viewMode, setViewMode] = useState<'list' | 'cards'>('list')
@ -204,11 +205,11 @@ const EmployeeList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={EmployeeStatusEnum.Active}>Aktif</option> {Object.values(EmployeeStatusEnum).map((status) => (
<option value={EmployeeStatusEnum.Inactive}>Pasif</option> <option key={status} value={status}>
<option value={EmployeeStatusEnum.OnLeave}>İzinli</option> {getEmployeeStatusText(status)}
<option value={EmployeeStatusEnum.Suspended}>Askıda</option> </option>
<option value={EmployeeStatusEnum.Terminated}>İşten Çıkarıldı</option> ))}
</select> </select>
</div> </div>
@ -220,10 +221,11 @@ const EmployeeList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value="IT">Bilgi İşlem</option> {mockDepartments.map((dept) => (
<option value="PROC">Satınalma</option> <option key={dept.id} value={dept.id}>
<option value="PROD">Üretim</option> {dept.name}
<option value="HR">İnsan Kaynakları</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -1,14 +1,16 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaSave, FaTimes, FaPlus, FaTrash } from "react-icons/fa"; import { FaSave, FaTimes, FaPlus, FaTrash } from 'react-icons/fa'
import { HrJobPosition, JobLevelEnum } from "../../../types/hr"; import { HrJobPosition, JobLevelEnum } from '../../../types/hr'
import { mockDepartments } from "../../../mocks/mockDepartments"; import { mockDepartments } from '../../../mocks/mockDepartments'
import { getJobLevelText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
interface JobPositionFormModalProps { interface JobPositionFormModalProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: (position: Partial<HrJobPosition>) => void; onSave: (position: Partial<HrJobPosition>) => void
position?: HrJobPosition; position?: HrJobPosition
title: string; title: string
} }
const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
@ -19,31 +21,31 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
title, title,
}) => { }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
positionCode: "", positionCode: '',
title: "", title: '',
description: "", description: '',
departmentId: "", departmentId: '',
level: JobLevelEnum.Entry, level: JobLevelEnum.Entry,
minSalary: 0, minSalary: 0,
maxSalary: 0, maxSalary: 0,
currency: "TRY", currency: 'TRY',
requiredSkills: [] as string[], requiredSkills: [] as string[],
responsibilities: [] as string[], responsibilities: [] as string[],
qualifications: [] as string[], qualifications: [] as string[],
isActive: true, isActive: true,
}); })
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({})
const [skillInput, setSkillInput] = useState(""); const [skillInput, setSkillInput] = useState('')
const [responsibilityInput, setResponsibilityInput] = useState(""); const [responsibilityInput, setResponsibilityInput] = useState('')
const [qualificationInput, setQualificationInput] = useState(""); const [qualificationInput, setQualificationInput] = useState('')
useEffect(() => { useEffect(() => {
if (position) { if (position) {
setFormData({ setFormData({
positionCode: position.code, positionCode: position.code,
title: position.name, title: position.name,
description: position.description || "", description: position.description || '',
departmentId: position.departmentId, departmentId: position.departmentId,
level: position.level, level: position.level,
minSalary: position.minSalary, minSalary: position.minSalary,
@ -53,97 +55,91 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
responsibilities: [...(position.responsibilities || [])], responsibilities: [...(position.responsibilities || [])],
qualifications: [...(position.qualifications || [])], qualifications: [...(position.qualifications || [])],
isActive: position.isActive, isActive: position.isActive,
}); })
} else { } else {
setFormData({ setFormData({
positionCode: "", positionCode: '',
title: "", title: '',
description: "", description: '',
departmentId: "", departmentId: '',
level: JobLevelEnum.Entry, level: JobLevelEnum.Entry,
minSalary: 0, minSalary: 0,
maxSalary: 0, maxSalary: 0,
currency: "TRY", currency: 'TRY',
requiredSkills: [], requiredSkills: [],
responsibilities: [], responsibilities: [],
qualifications: [], qualifications: [],
isActive: true, isActive: true,
}); })
} }
setErrors({}); setErrors({})
setSkillInput(""); setSkillInput('')
setResponsibilityInput(""); setResponsibilityInput('')
setQualificationInput(""); setQualificationInput('')
}, [position, isOpen]); }, [position, isOpen])
const validateForm = (): boolean => { const validateForm = (): boolean => {
const newErrors: Record<string, string> = {}; const newErrors: Record<string, string> = {}
if (!formData.positionCode.trim()) { if (!formData.positionCode.trim()) {
newErrors.positionCode = "Pozisyon kodu zorunludur"; newErrors.positionCode = 'Pozisyon kodu zorunludur'
} }
if (!formData.title.trim()) { if (!formData.title.trim()) {
newErrors.title = "Pozisyon adı zorunludur"; newErrors.title = 'Pozisyon adı zorunludur'
} }
if (!formData.departmentId) { if (!formData.departmentId) {
newErrors.departmentId = "Departman seçimi zorunludur"; newErrors.departmentId = 'Departman seçimi zorunludur'
} }
if (formData.minSalary < 0) { if (formData.minSalary < 0) {
newErrors.minSalary = "Minimum maaş negatif olamaz"; newErrors.minSalary = 'Minimum maaş negatif olamaz'
} }
if (formData.maxSalary < 0) { if (formData.maxSalary < 0) {
newErrors.maxSalary = "Maksimum maaş negatif olamaz"; newErrors.maxSalary = 'Maksimum maaş negatif olamaz'
} }
if (formData.maxSalary < formData.minSalary) { if (formData.maxSalary < formData.minSalary) {
newErrors.maxSalary = "Maksimum maaş minimum maaştan düşük olamaz"; newErrors.maxSalary = 'Maksimum maaş minimum maaştan düşük olamaz'
} }
setErrors(newErrors); setErrors(newErrors)
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (validateForm()) { if (validateForm()) {
onSave(formData); onSave(formData)
onClose(); onClose()
} }
}; }
const handleInputChange = ( const handleInputChange = (field: string, value: string | number | boolean | JobLevelEnum) => {
field: string,
value: string | number | boolean | JobLevelEnum
) => {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[field]: value, [field]: value,
})); }))
}; }
const addSkill = () => { const addSkill = () => {
if ( if (skillInput.trim() && !formData.requiredSkills.includes(skillInput.trim())) {
skillInput.trim() &&
!formData.requiredSkills.includes(skillInput.trim())
) {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
requiredSkills: [...prev.requiredSkills, skillInput.trim()], requiredSkills: [...prev.requiredSkills, skillInput.trim()],
})); }))
setSkillInput(""); setSkillInput('')
} }
}; }
const removeSkill = (index: number) => { const removeSkill = (index: number) => {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
requiredSkills: prev.requiredSkills.filter((_, i) => i !== index), requiredSkills: prev.requiredSkills.filter((_, i) => i !== index),
})); }))
}; }
const addResponsibility = () => { const addResponsibility = () => {
if ( if (
@ -152,53 +148,44 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
) { ) {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
responsibilities: [ responsibilities: [...prev.responsibilities, responsibilityInput.trim()],
...prev.responsibilities, }))
responsibilityInput.trim(), setResponsibilityInput('')
],
}));
setResponsibilityInput("");
} }
}; }
const removeResponsibility = (index: number) => { const removeResponsibility = (index: number) => {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
responsibilities: prev.responsibilities.filter((_, i) => i !== index), responsibilities: prev.responsibilities.filter((_, i) => i !== index),
})); }))
}; }
const addQualification = () => { const addQualification = () => {
if ( if (qualificationInput.trim() && !formData.qualifications.includes(qualificationInput.trim())) {
qualificationInput.trim() &&
!formData.qualifications.includes(qualificationInput.trim())
) {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
qualifications: [...prev.qualifications, qualificationInput.trim()], qualifications: [...prev.qualifications, qualificationInput.trim()],
})); }))
setQualificationInput(""); setQualificationInput('')
} }
}; }
const removeQualification = (index: number) => { const removeQualification = (index: number) => {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
qualifications: prev.qualifications.filter((_, i) => i !== index), qualifications: prev.qualifications.filter((_, i) => i !== index),
})); }))
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-3 border-b"> <div className="flex items-center justify-between p-3 border-b">
<h2 className="text-xl font-bold text-gray-900">{title}</h2> <h2 className="text-xl font-bold text-gray-900">{title}</h2>
<button <button onClick={onClose} className="p-1 hover:bg-gray-100 rounded-full">
onClick={onClose}
className="p-1 hover:bg-gray-100 rounded-full"
>
<FaTimes className="w-5 h-5" /> <FaTimes className="w-5 h-5" />
</button> </button>
</div> </div>
@ -214,47 +201,37 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
autoFocus autoFocus
type="text" type="text"
value={formData.positionCode} value={formData.positionCode}
onChange={(e) => onChange={(e) => handleInputChange('positionCode', e.target.value)}
handleInputChange("positionCode", e.target.value)
}
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.positionCode ? "border-red-500" : "border-gray-300" errors.positionCode ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Örn: DEV-001" placeholder="Örn: DEV-001"
/> />
{errors.positionCode && ( {errors.positionCode && (
<p className="text-red-500 text-sm mt-1"> <p className="text-red-500 text-sm mt-1">{errors.positionCode}</p>
{errors.positionCode}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Pozisyon Adı *</label>
Pozisyon Adı *
</label>
<input <input
type="text" type="text"
value={formData.title} value={formData.title}
onChange={(e) => handleInputChange("title", e.target.value)} onChange={(e) => handleInputChange('title', e.target.value)}
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.title ? "border-red-500" : "border-gray-300" errors.title ? 'border-red-500' : 'border-gray-300'
}`} }`}
placeholder="Örn: Software Developer" placeholder="Örn: Software Developer"
/> />
{errors.title && ( {errors.title && <p className="text-red-500 text-sm mt-1">{errors.title}</p>}
<p className="text-red-500 text-sm mt-1">{errors.title}</p>
)}
</div> </div>
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">ıklama</label>
ıklama
</label>
<textarea <textarea
value={formData.description} value={formData.description}
onChange={(e) => handleInputChange("description", e.target.value)} onChange={(e) => handleInputChange('description', e.target.value)}
rows={2} rows={2}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Pozisyon açıklaması..." placeholder="Pozisyon açıklaması..."
@ -263,16 +240,12 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Departman *</label>
Departman *
</label>
<select <select
value={formData.departmentId} value={formData.departmentId}
onChange={(e) => onChange={(e) => handleInputChange('departmentId', e.target.value)}
handleInputChange("departmentId", e.target.value)
}
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.departmentId ? "border-red-500" : "border-gray-300" errors.departmentId ? 'border-red-500' : 'border-gray-300'
}`} }`}
> >
<option value="">Departman seçin</option> <option value="">Departman seçin</option>
@ -283,33 +256,22 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
))} ))}
</select> </select>
{errors.departmentId && ( {errors.departmentId && (
<p className="text-red-500 text-sm mt-1"> <p className="text-red-500 text-sm mt-1">{errors.departmentId}</p>
{errors.departmentId}
</p>
)} )}
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Seviye</label>
Seviye
</label>
<select <select
value={formData.level} value={formData.level}
onChange={(e) => onChange={(e) => handleInputChange('level', e.target.value as JobLevelEnum)}
handleInputChange("level", e.target.value as JobLevelEnum)
}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={JobLevelEnum.Entry}>Giriş Seviyesi</option> {Object.values(JobLevelEnum).map((level) => (
<option value={JobLevelEnum.Junior}>Junior</option> <option key={level} value={level}>
<option value={JobLevelEnum.Mid}>Orta Seviye</option> {getJobLevelText(level)}
<option value={JobLevelEnum.Senior}>Senior</option> </option>
<option value={JobLevelEnum.Lead}>Lider</option> ))}
<option value={JobLevelEnum.Manager}>Yönetici</option>
<option value={JobLevelEnum.Director}>Direktör</option>
<option value={JobLevelEnum.Executive}>
Üst Düzey Yönetici
</option>
</select> </select>
</div> </div>
</div> </div>
@ -317,23 +279,17 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
{/* Salary Information */} {/* Salary Information */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Minimum Maaş *</label>
Minimum Maaş *
</label>
<input <input
type="number" type="number"
value={formData.minSalary} value={formData.minSalary}
onChange={(e) => onChange={(e) => handleInputChange('minSalary', Number(e.target.value))}
handleInputChange("minSalary", Number(e.target.value))
}
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.minSalary ? "border-red-500" : "border-gray-300" errors.minSalary ? 'border-red-500' : 'border-gray-300'
}`} }`}
min="0" min="0"
/> />
{errors.minSalary && ( {errors.minSalary && <p className="text-red-500 text-sm mt-1">{errors.minSalary}</p>}
<p className="text-red-500 text-sm mt-1">{errors.minSalary}</p>
)}
</div> </div>
<div> <div>
@ -343,31 +299,27 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
<input <input
type="number" type="number"
value={formData.maxSalary} value={formData.maxSalary}
onChange={(e) => onChange={(e) => handleInputChange('maxSalary', Number(e.target.value))}
handleInputChange("maxSalary", Number(e.target.value))
}
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
errors.maxSalary ? "border-red-500" : "border-gray-300" errors.maxSalary ? 'border-red-500' : 'border-gray-300'
}`} }`}
min="0" min="0"
/> />
{errors.maxSalary && ( {errors.maxSalary && <p className="text-red-500 text-sm mt-1">{errors.maxSalary}</p>}
<p className="text-red-500 text-sm mt-1">{errors.maxSalary}</p>
)}
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Para Birimi</label>
Para Birimi
</label>
<select <select
value={formData.currency} value={formData.currency}
onChange={(e) => handleInputChange("currency", e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -382,9 +334,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
type="text" type="text"
value={skillInput} value={skillInput}
onChange={(e) => setSkillInput(e.target.value)} onChange={(e) => setSkillInput(e.target.value)}
onKeyPress={(e) => onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), addSkill())}
e.key === "Enter" && (e.preventDefault(), addSkill())
}
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Yetenek ekleyin..." placeholder="Yetenek ekleyin..."
/> />
@ -417,17 +367,13 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
{/* Responsibilities */} {/* Responsibilities */}
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Sorumluluklar</label>
Sorumluluklar
</label>
<div className="flex gap-2 mb-2"> <div className="flex gap-2 mb-2">
<input <input
type="text" type="text"
value={responsibilityInput} value={responsibilityInput}
onChange={(e) => setResponsibilityInput(e.target.value)} onChange={(e) => setResponsibilityInput(e.target.value)}
onKeyPress={(e) => onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), addResponsibility())}
e.key === "Enter" && (e.preventDefault(), addResponsibility())
}
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Sorumluluk ekleyin..." placeholder="Sorumluluk ekleyin..."
/> />
@ -445,9 +391,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
key={index} key={index}
className="flex items-center justify-between p-2 bg-green-50 rounded-md text-sm" className="flex items-center justify-between p-2 bg-green-50 rounded-md text-sm"
> >
<span className="text-green-800 text-sm"> <span className="text-green-800 text-sm">{responsibility}</span>
{responsibility}
</span>
<button <button
type="button" type="button"
onClick={() => removeResponsibility(index)} onClick={() => removeResponsibility(index)}
@ -462,17 +406,13 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
{/* Qualifications */} {/* Qualifications */}
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <label className="block text-xs font-medium text-gray-700 mb-1">Nitelikler</label>
Nitelikler
</label>
<div className="flex gap-2 mb-2"> <div className="flex gap-2 mb-2">
<input <input
type="text" type="text"
value={qualificationInput} value={qualificationInput}
onChange={(e) => setQualificationInput(e.target.value)} onChange={(e) => setQualificationInput(e.target.value)}
onKeyPress={(e) => onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), addQualification())}
e.key === "Enter" && (e.preventDefault(), addQualification())
}
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Nitelik ekleyin..." placeholder="Nitelik ekleyin..."
/> />
@ -490,9 +430,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
key={index} key={index}
className="flex items-center justify-between p-2 bg-purple-50 rounded-md text-sm" className="flex items-center justify-between p-2 bg-purple-50 rounded-md text-sm"
> >
<span className="text-purple-800 text-sm"> <span className="text-purple-800 text-sm">{qualification}</span>
{qualification}
</span>
<button <button
type="button" type="button"
onClick={() => removeQualification(index)} onClick={() => removeQualification(index)}
@ -511,13 +449,10 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
type="checkbox" type="checkbox"
id="isActive" id="isActive"
checked={formData.isActive} checked={formData.isActive}
onChange={(e) => handleInputChange("isActive", e.target.checked)} onChange={(e) => handleInputChange('isActive', e.target.checked)}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/> />
<label <label htmlFor="isActive" className="ml-2 block text-sm text-gray-900">
htmlFor="isActive"
className="ml-2 block text-sm text-gray-900"
>
Aktif pozisyon Aktif pozisyon
</label> </label>
</div> </div>
@ -543,7 +478,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default JobPositionFormModal; export default JobPositionFormModal

View file

@ -336,9 +336,7 @@ const JobPositions: React.FC = () => {
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
<div> <div>
<h2 className="text-2xl font-bold text-gray-900">İş Pozisyonları</h2> <h2 className="text-2xl font-bold text-gray-900">İş Pozisyonları</h2>
<p className="text-gray-600"> <p className="text-gray-600">Şirket pozisyonları ve tanımları yönetimi</p>
Şirket pozisyonları ve tanımları yönetimi
</p>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{/* View Toggle */} {/* View Toggle */}
@ -442,14 +440,11 @@ const JobPositions: React.FC = () => {
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 min-w-0 sm:min-w-[160px]" className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 min-w-0 sm:min-w-[160px]"
> >
<option value="all">Tüm Seviyeler</option> <option value="all">Tüm Seviyeler</option>
<option value={JobLevelEnum.Entry}>Giriş Seviyesi</option> {Object.values(JobLevelEnum).map((level) => (
<option value={JobLevelEnum.Junior}>Junior</option> <option key={level} value={level}>
<option value={JobLevelEnum.Mid}>Orta Seviye</option> {getJobLevelText(level)}
<option value={JobLevelEnum.Senior}>Senior</option> </option>
<option value={JobLevelEnum.Lead}>Lider</option> ))}
<option value={JobLevelEnum.Manager}>Yönetici</option>
<option value={JobLevelEnum.Director}>Direktör</option>
<option value={JobLevelEnum.Executive}>Üst Düzey Yönetici</option>
</select> </select>
<select <select

View file

@ -506,10 +506,11 @@ const LeaveManagement: React.FC = () => {
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={LeaveStatusEnum.Pending}>Beklemede</option> {Object.values(LeaveStatusEnum).map((status) => (
<option value={LeaveStatusEnum.Approved}>Onaylandı</option> <option key={status} value={status}>
<option value={LeaveStatusEnum.Rejected}>Reddedildi</option> {getLeaveStatusText(status)}
<option value={LeaveStatusEnum.Cancelled}>İptal Edildi</option> </option>
))}
</select> </select>
<select <select
@ -518,14 +519,11 @@ const LeaveManagement: React.FC = () => {
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm İzin Türleri</option> <option value="all">Tüm İzin Türleri</option>
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option> {Object.values(LeaveTypeEnum).map((type) => (
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option> <option key={type} value={type}>
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option> {getLeaveTypeText(type)}
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</option> </option>
<option value={LeaveTypeEnum.Personal}>Kişisel İzin</option> ))}
<option value={LeaveTypeEnum.Emergency}>Acil Durum İzni</option>
<option value={LeaveTypeEnum.Study}>Eğitim İzni</option>
<option value={LeaveTypeEnum.Unpaid}>Ücretsiz İzin</option>
</select> </select>
<select <select
@ -591,14 +589,11 @@ const LeaveManagement: React.FC = () => {
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option> {Object.values(LeaveTypeEnum).map((type) => (
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option> <option key={type} value={type}>
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option> {getLeaveTypeText(type)}
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</option> </option>
<option value={LeaveTypeEnum.Personal}>Kişisel İzin</option> ))}
<option value={LeaveTypeEnum.Emergency}>Acil Durum İzni</option>
<option value={LeaveTypeEnum.Study}>Eğitim İzni</option>
<option value={LeaveTypeEnum.Unpaid}>Ücretsiz İzin</option>
</select> </select>
</div> </div>
@ -933,14 +928,11 @@ const LeaveManagement: React.FC = () => {
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option> {Object.values(LeaveStatusEnum).map((status) => (
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option> <option key={status} value={status}>
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option> {getLeaveStatusText(status)}
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</option> </option>
<option value={LeaveTypeEnum.Personal}>Kişisel İzin</option> ))}
<option value={LeaveTypeEnum.Emergency}>Acil Durum İzni</option>
<option value={LeaveTypeEnum.Study}>Eğitim İzni</option>
<option value={LeaveTypeEnum.Unpaid}>Ücretsiz İzin</option>
</select> </select>
</div> </div>

View file

@ -544,9 +544,11 @@ const OvertimeManagement: React.FC = () => {
className="border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={LeaveStatusEnum.Pending}>Beklemede</option> {Object.values(LeaveStatusEnum).map((status) => (
<option value={LeaveStatusEnum.Approved}>Onaylı</option> <option key={status} value={status}>
<option value={LeaveStatusEnum.Rejected}>Reddedildi</option> {getLeaveStatusText(status)}
</option>
))}
</select> </select>
<select <select

View file

@ -515,11 +515,11 @@ const PayrollManagement: React.FC = () => {
className="px-3 py-1.5 border border-gray-300 text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 py-1.5 border border-gray-300 text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={PayrollStatusEnum.Draft}>Taslak</option> {Object.values(PayrollStatusEnum).map((status) => (
<option value={PayrollStatusEnum.Calculated}>Hesaplandı</option> <option key={status} value={status}>
<option value={PayrollStatusEnum.Approved}>Onaylandı</option> {getPayrollStatusText(status)}
<option value={PayrollStatusEnum.Paid}>Ödendi</option> </option>
<option value={PayrollStatusEnum.Cancelled}>İptal Edildi</option> ))}
</select> </select>
<select <select

View file

@ -137,12 +137,21 @@ const ChangeNotificationStatusModal: React.FC<ChangeNotificationStatusModalProps
errors.status ? 'border-red-500' : 'border-gray-300' errors.status ? 'border-red-500' : 'border-gray-300'
}`} }`}
> >
<option value={NotificationStatusEnum.Open}>ık</option> {Object.keys(NotificationStatusEnum).map((key) => (
<option value={NotificationStatusEnum.Assigned}>Atandı</option> <option
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option> key={key}
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option> value={NotificationStatusEnum[key as keyof typeof NotificationStatusEnum]}
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option> >
<option value={NotificationStatusEnum.Rejected}>Reddedildi</option> {getNotificationStatusText(
NotificationStatusEnum[key as keyof typeof NotificationStatusEnum],
)}
</option>
))}
{Object.values(NotificationStatusEnum).map((status) => (
<option key={status} value={status}>
{getNotificationStatusText(status)}
</option>
))}
</select> </select>
{errors.status && <p className="text-red-500 text-sm mt-1">{errors.status}</p>} {errors.status && <p className="text-red-500 text-sm mt-1">{errors.status}</p>}
</div> </div>

View file

@ -5,6 +5,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
import { PmFaultNotification, WorkOrderTypeEnum } from '../../../types/pm' import { PmFaultNotification, WorkOrderTypeEnum } from '../../../types/pm'
import { MrpWorkOrder } from '../../../types/mrp' import { MrpWorkOrder } from '../../../types/mrp'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getPriorityText, getWorkOrderTypeText } from '@/utils/erp'
interface CreateWorkOrderFromNotificationModalProps { interface CreateWorkOrderFromNotificationModalProps {
isOpen: boolean isOpen: boolean
@ -163,11 +164,11 @@ const CreateWorkOrderFromNotificationModal: React.FC<CreateWorkOrderFromNotifica
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkOrderTypeEnum.Preventive}>Önleyici Bakım</option> {Object.values(WorkOrderTypeEnum).map((type) => (
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici Bakım</option> <option key={type} value={type}>
<option value={WorkOrderTypeEnum.Emergency}>Acil Müdahale</option> {getWorkOrderTypeText(type)}
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option> </option>
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option> ))}
</select> </select>
</div> </div>
</div> </div>
@ -180,10 +181,11 @@ const CreateWorkOrderFromNotificationModal: React.FC<CreateWorkOrderFromNotifica
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)} onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -8,7 +8,7 @@ import {
} from '../../../types/pm' } from '../../../types/pm'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getPriorityColor } from '../../../utils/erp' import { getPriorityColor, getPriorityText } from '../../../utils/erp'
interface CreateWorkOrderModalProps { interface CreateWorkOrderModalProps {
isOpen: boolean isOpen: boolean
@ -243,10 +243,11 @@ const CreateWorkOrderModal: React.FC<CreateWorkOrderModalProps> = ({
onChange={(e) => handleCommonChange('priority', e.target.value as PriorityEnum)} onChange={(e) => handleCommonChange('priority', e.target.value as PriorityEnum)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -329,10 +330,11 @@ const CreateWorkOrderModal: React.FC<CreateWorkOrderModalProps> = ({
className="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-1 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="">Ortak ayarı kullan</option> <option value="">Ortak ayarı kullan</option>
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>

View file

@ -9,6 +9,12 @@ import {
import { mockWorkCenters } from '../../../mocks/mockWorkCenters' import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import {
getCriticalityLevelText,
getFaultTypeText,
getNotificationStatusText,
getPriorityText,
} from '@/utils/erp'
interface EditFaultNotificationModalProps { interface EditFaultNotificationModalProps {
isOpen: boolean isOpen: boolean
@ -260,12 +266,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={NotificationStatusEnum.Open}>ık</option> {Object.values(NotificationStatusEnum).map((status) => (
<option value={NotificationStatusEnum.Assigned}>Atandı</option> <option key={status} value={status}>
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option> {getNotificationStatusText(status)}
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option> </option>
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option> ))}
<option value={NotificationStatusEnum.Rejected}>Reddedildi</option>
</select> </select>
</div> </div>
@ -294,14 +299,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)} onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={FaultTypeEnum.Mechanical}>Mekanik</option> {Object.values(FaultTypeEnum).map((faultType) => (
<option value={FaultTypeEnum.Electrical}>Elektrik</option> <option key={faultType} value={faultType}>
<option value={FaultTypeEnum.Hydraulic}>Hidrolik</option> {getFaultTypeText(faultType)}
<option value={FaultTypeEnum.Pneumatic}>Pnömatik</option> </option>
<option value={FaultTypeEnum.Software}>Yazılım</option> ))}
<option value={FaultTypeEnum.Safety}>Güvenlik</option>
<option value={FaultTypeEnum.Performance}>Performans</option>
<option value={FaultTypeEnum.Other}>Diğer</option>
</select> </select>
</div> </div>
@ -312,10 +314,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)} onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
@ -328,10 +331,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={CriticalityLevelEnum.Low}>Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Medium}>Orta</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.High}>Yüksek</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.Critical}>Kritik</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -10,6 +10,7 @@ import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { mockMaterials } from '../../../mocks/mockMaterials' import { mockMaterials } from '../../../mocks/mockMaterials'
import { mockUnits } from '../../../mocks/mockUnits' import { mockUnits } from '../../../mocks/mockUnits'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getFrequencyUnitText, getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
interface EditMaintenancePlanModalProps { interface EditMaintenancePlanModalProps {
isOpen: boolean isOpen: boolean
@ -154,10 +155,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option> {Object.values(MaintenancePlanTypeEnum).map((type) => (
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option> <option key={type} value={type}>
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option> {getMaintenancePlanTypeText(type)}
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -168,10 +170,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
<div className="md:col-span-2"> <div className="md:col-span-2">
@ -214,12 +217,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={FrequencyUnitEnum.Days}>Gün</option> {Object.values(FrequencyUnitEnum).map((unit) => (
<option value={FrequencyUnitEnum.Weeks}>Hafta</option> <option key={unit} value={unit}>
<option value={FrequencyUnitEnum.Months}>Ay</option> {getFrequencyUnitText(unit)}
<option value={FrequencyUnitEnum.Years}>Yıl</option> </option>
<option value={FrequencyUnitEnum.Hours}>Saat</option> ))}
<option value={FrequencyUnitEnum.Cycles}>Çevrim</option>
</select> </select>
</div> </div>
<div> <div>

View file

@ -3,6 +3,7 @@ import { FaTimes, FaSave, FaPlus, FaMinus } from 'react-icons/fa'
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee' import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common' import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
import { getTeamRoleText } from '@/utils/erp'
interface EditTeamModalProps { interface EditTeamModalProps {
isOpen: boolean isOpen: boolean
@ -252,9 +253,13 @@ const EditTeamModal: React.FC<EditTeamModalProps> = ({ isOpen, onClose, onSave,
} }
className="text-xs px-2 py-1 border border-gray-300 rounded" className="text-xs px-2 py-1 border border-gray-300 rounded"
> >
<option value={TeamRoleEnum.Member}>Üye</option> {Object.values(TeamRoleEnum)
<option value={TeamRoleEnum.Lead}>Lider</option> .filter((a) => a !== TeamRoleEnum.Manager)
<option value={TeamRoleEnum.Specialist}>Uzman</option> .map((role) => (
<option key={role} value={role}>
{getTeamRoleText(role)}
</option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -7,6 +7,8 @@ import {
PmWorkCenterSpecification, PmWorkCenterSpecification,
} from '../../../types/pm' } from '../../../types/pm'
import { mockDepartments } from '../../../mocks/mockDepartments' import { mockDepartments } from '../../../mocks/mockDepartments'
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
import { mockWorkCenterMachineTypes } from '@/mocks/mockWorkCenterMachineTypes'
interface EditWorkCenterModalProps { interface EditWorkCenterModalProps {
isOpen: boolean isOpen: boolean
@ -138,14 +140,15 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
<label className="block text-sm font-medium text-gray-700 mb-2">Makine Türü</label> <label className="block text-sm font-medium text-gray-700 mb-2">Makine Türü</label>
<select <select
name="machineType" name="machineType"
value={formData.machineType || 'Manual'} value={formData.machineType?.id}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="Manual">Manuel</option> {mockWorkCenterMachineTypes.map((type) => (
<option value="CNC">CNC</option> <option key={type.id} value={type.id}>
<option value="Automated">Otomatik</option> {type.name}
<option value="Semi-Automated">Yarı Otomatik</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -290,10 +293,11 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option> {Object.values(WorkCenterStatusEnum).map((status) => (
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option> <option key={status} value={status}>
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option> {getWorkCenterStatusText(status)}
<option value={WorkCenterStatusEnum.Retired}>Emekli</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -306,10 +310,11 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={CriticalityLevelEnum.Low}>Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Medium}>Orta</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.High}>Yüksek</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.Critical}>Kritik</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>

View file

@ -12,6 +12,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { mockMaterials } from '../../../mocks/mockMaterials' import { mockMaterials } from '../../../mocks/mockMaterials'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getPriorityText, getWorkOrderStatusText, getWorkOrderTypeText } from '@/utils/erp'
interface EditWorkOrderModalProps { interface EditWorkOrderModalProps {
isOpen: boolean isOpen: boolean
@ -269,13 +270,11 @@ const EditWorkOrderModal: React.FC<EditWorkOrderModalProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option> {Object.values(WorkOrderStatusEnum).map((status) => (
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option> <option key={status} value={status}>
<option value={WorkOrderStatusEnum.Released}>Serbest Bırakıldı</option> {getWorkOrderStatusText(status)}
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option> </option>
<option value={WorkOrderStatusEnum.OnHold}>Beklemede</option> ))}
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
<option value={WorkOrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>
@ -312,11 +311,11 @@ const EditWorkOrderModal: React.FC<EditWorkOrderModalProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option> {Object.values(WorkOrderTypeEnum).map((type) => (
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option> <option key={type} value={type}>
<option value={WorkOrderTypeEnum.Emergency}>Acil</option> {getWorkOrderTypeText(type)}
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option> </option>
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option> ))}
</select> </select>
</div> </div>
@ -332,10 +331,11 @@ const EditWorkOrderModal: React.FC<EditWorkOrderModalProps> = ({
} }
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -254,12 +254,11 @@ const FaultNotifications: React.FC = () => {
onChange={(e) => setStatusFilter(e.target.value as NotificationStatusEnum | 'all')} onChange={(e) => setStatusFilter(e.target.value as NotificationStatusEnum | 'all')}
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Durumlar</option> {Object.values(NotificationStatusEnum).map((status) => (
<option value={NotificationStatusEnum.Open}>ık</option> <option key={status} value={status}>
<option value={NotificationStatusEnum.Assigned}>Atandı</option> {getNotificationStatusText(status)}
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option> </option>
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option> ))}
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
</select> </select>
</div> </div>
<div className="relative"> <div className="relative">
@ -269,10 +268,11 @@ const FaultNotifications: React.FC = () => {
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Öncelikler</option> <option value="all">Tüm Öncelikler</option>
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -16,6 +16,7 @@ import {
getPriorityColor, getPriorityColor,
getWorkOrderStatusColor, getWorkOrderStatusColor,
getWorkOrderStatusIcon, getWorkOrderStatusIcon,
getWorkOrderStatusText,
} from '../../../utils/erp' } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
@ -312,10 +313,11 @@ const MaintenanceCalendar: React.FC = () => {
className="pl-9 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" className="pl-9 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value="scheduled">Planlanmış</option> {Object.values(WorkOrderStatusEnum).map((status) => (
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option> <option key={status} value={status}>
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option> {getWorkOrderStatusText(status)}
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option> </option>
))}
</select> </select>
</div> </div>
<button <button

View file

@ -7,6 +7,7 @@ import {
PmMaintenancePlan, PmMaintenancePlan,
} from '../../../types/pm' } from '../../../types/pm'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
interface MaintenancePlanModalProps { interface MaintenancePlanModalProps {
isOpen: boolean isOpen: boolean
@ -123,10 +124,11 @@ const MaintenancePlanModal: React.FC<MaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option> {Object.values(MaintenancePlanTypeEnum).map((type) => (
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option> <option key={type} value={type}>
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option> {getMaintenancePlanTypeText(type)}
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -137,10 +139,11 @@ const MaintenancePlanModal: React.FC<MaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -25,7 +25,7 @@ import PlanStatusChangeModal from './PlanStatusChangeModal'
import Widget from '../../../components/common/Widget' import Widget from '../../../components/common/Widget'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { import {
getFrequencyUnitText, getFrequencyUnitTextByFrequency,
getMaintenancePlanTypeColor, getMaintenancePlanTypeColor,
getMaintenancePlanTypeText, getMaintenancePlanTypeText,
getPriorityColor, getPriorityColor,
@ -194,11 +194,11 @@ const MaintenancePlans: React.FC = () => {
onChange={(e) => setTypeFilter(e.target.value as MaintenancePlanTypeEnum | 'all')} onChange={(e) => setTypeFilter(e.target.value as MaintenancePlanTypeEnum | 'all')}
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Tipler</option> {Object.values(MaintenancePlanTypeEnum).map((type) => (
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici</option> <option key={type} value={type}>
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici</option> {getMaintenancePlanTypeText(type)}
<option value={MaintenancePlanTypeEnum.Predictive}>Tahminsel</option> </option>
<option value={MaintenancePlanTypeEnum.Condition}>Duruma Bağlı</option> ))}
</select> </select>
</div> </div>
<div className="relative"> <div className="relative">
@ -313,7 +313,7 @@ const MaintenancePlans: React.FC = () => {
</td> </td>
<td className="px-4 py-3 whitespace-nowrap"> <td className="px-4 py-3 whitespace-nowrap">
<div className="text-sm text-gray-900"> <div className="text-sm text-gray-900">
{getFrequencyUnitText(plan.frequency, plan.frequencyUnit)} {getFrequencyUnitTextByFrequency(plan.frequency, plan.frequencyUnit)}
</div> </div>
<div className="text-xs text-gray-500">{plan.estimatedDuration} dakika</div> <div className="text-xs text-gray-500">{plan.estimatedDuration} dakika</div>
</td> </td>

View file

@ -187,9 +187,11 @@ const MaintenanceTeams: React.FC = () => {
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Roller</option> <option value="all">Tüm Roller</option>
<option value={TeamRoleEnum.Lead}>Lider</option> {Object.values(TeamRoleEnum).map((role) => (
<option value={TeamRoleEnum.Specialist}>Uzman</option> <option key={role} value={role}>
<option value={TeamRoleEnum.Member}>Üye</option> {getTeamRoleText(role)}
</option>
))}
</select> </select>
</div> </div>
<div className="relative"> <div className="relative">

View file

@ -274,10 +274,11 @@ const MaintenanceWorkOrders: React.FC = () => {
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option> {Object.values(WorkOrderStatusEnum).map((status) => (
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option> <option key={status} value={status}>
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option> {getWorkOrderStatusText(status)}
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option> </option>
))}
</select> </select>
</div> </div>
<div className="relative"> <div className="relative">
@ -287,11 +288,11 @@ const MaintenanceWorkOrders: React.FC = () => {
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Tipler</option> <option value="all">Tüm Tipler</option>
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option> {Object.values(WorkOrderTypeEnum).map((type) => (
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option> <option key={type} value={type}>
<option value={WorkOrderTypeEnum.Emergency}>Acil</option> {getWorkOrderTypeText(type)}
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option> </option>
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option> ))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -4,6 +4,7 @@ import { PmCalendarEvent, WorkOrderStatusEnum } from '../../../types/pm'
import { mockWorkCenters } from '../../../mocks/mockWorkCenters' import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getPriorityText, getWorkOrderStatusText } from '@/utils/erp'
interface NewCalendarEventModalProps { interface NewCalendarEventModalProps {
isOpen: boolean isOpen: boolean
@ -220,10 +221,11 @@ const NewCalendarEventModal: React.FC<NewCalendarEventModalProps> = ({
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)} onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
@ -331,14 +333,11 @@ const NewCalendarEventModal: React.FC<NewCalendarEventModalProps> = ({
} }
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="scheduled">Planlanmış</option> {Object.values(WorkOrderStatusEnum).map((status) => (
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option> <option key={status} value={status}>
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option> {getWorkOrderStatusText(status)}
<option value={WorkOrderStatusEnum.Released}>Serbest Bırakıldı</option> </option>
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option> ))}
<option value={WorkOrderStatusEnum.OnHold}>Beklemede</option>
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
<option value={WorkOrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>
)} )}

View file

@ -9,6 +9,7 @@ import {
import { mockWorkCenters } from '../../../mocks/mockWorkCenters' import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getCriticalityLevelText, getFaultTypeText, getPriorityText } from '@/utils/erp'
interface NewFaultNotificationModalProps { interface NewFaultNotificationModalProps {
isOpen: boolean isOpen: boolean
@ -274,14 +275,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)} onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={FaultTypeEnum.Mechanical}>Mekanik</option> {Object.values(FaultTypeEnum).map((faultType) => (
<option value={FaultTypeEnum.Electrical}>Elektrik</option> <option key={faultType} value={faultType}>
<option value={FaultTypeEnum.Hydraulic}>Hidrolik</option> {getFaultTypeText(faultType)}
<option value={FaultTypeEnum.Pneumatic}>Pnömatik</option> </option>
<option value={FaultTypeEnum.Software}>Yazılım</option> ))}
<option value={FaultTypeEnum.Safety}>Güvenlik</option>
<option value={FaultTypeEnum.Performance}>Performans</option>
<option value={FaultTypeEnum.Other}>Diğer</option>
</select> </select>
</div> </div>
@ -292,10 +290,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)} onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
@ -308,10 +307,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
} }
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={CriticalityLevelEnum.Low}>Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Medium}>Orta</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.High}>Yüksek</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.Critical}>Kritik</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -10,6 +10,7 @@ import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { mockMaterials } from '../../../mocks/mockMaterials' import { mockMaterials } from '../../../mocks/mockMaterials'
import { mockUnits } from '../../../mocks/mockUnits' import { mockUnits } from '../../../mocks/mockUnits'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getFrequencyUnitText, getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
interface NewMaintenancePlanModalProps { interface NewMaintenancePlanModalProps {
isOpen: boolean isOpen: boolean
@ -158,10 +159,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option> {Object.values(MaintenancePlanTypeEnum).map((type) => (
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option> <option key={type} value={type}>
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option> {getMaintenancePlanTypeText(type)}
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -172,10 +174,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
<div className="md:col-span-2"> <div className="md:col-span-2">
@ -219,12 +222,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={FrequencyUnitEnum.Days}>Gün</option> {Object.values(FrequencyUnitEnum).map((unit) => (
<option value={FrequencyUnitEnum.Weeks}>Hafta</option> <option key={unit} value={unit}>
<option value={FrequencyUnitEnum.Months}>Ay</option> {getFrequencyUnitText(unit)}
<option value={FrequencyUnitEnum.Years}>Yıl</option> </option>
<option value={FrequencyUnitEnum.Hours}>Saat</option> ))}
<option value={FrequencyUnitEnum.Cycles}>Çevrim</option>
</select> </select>
</div> </div>
<div> <div>

View file

@ -4,6 +4,7 @@ import { TeamRoleEnum } from '../../../types/common'
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee' import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { Team, TeamMember } from '../../../types/common' import { Team, TeamMember } from '../../../types/common'
import { getTeamRoleText } from '@/utils/erp'
interface NewTeamModalProps { interface NewTeamModalProps {
isOpen: boolean isOpen: boolean
@ -259,10 +260,11 @@ const NewTeamModal: React.FC<NewTeamModalProps> = ({ isOpen, onClose, onSave })
} }
className="text-xs px-1.5 py-1 border border-gray-300 rounded" className="text-xs px-1.5 py-1 border border-gray-300 rounded"
> >
<option value={TeamRoleEnum.Member}>Üye</option> {Object.values(TeamRoleEnum).map((role) => (
<option value={TeamRoleEnum.Lead}>Lider</option> <option key={role} value={role}>
<option value={TeamRoleEnum.Specialist}>Uzman</option> {getTeamRoleText(role)}
<option value={TeamRoleEnum.Manager}>Yönetici</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -6,6 +6,7 @@ import {
CriticalityLevelEnum, CriticalityLevelEnum,
PmWorkCenterSpecification, PmWorkCenterSpecification,
} from '../../../types/pm' } from '../../../types/pm'
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
interface NewWorkCenterModalProps { interface NewWorkCenterModalProps {
isOpen: boolean isOpen: boolean
@ -249,10 +250,11 @@ const NewWorkCenterModal: React.FC<NewWorkCenterModalProps> = ({ isOpen, onClose
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option> {Object.values(WorkCenterStatusEnum).map((status) => (
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option> <option key={status} value={status}>
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option> {getWorkCenterStatusText(status)}
<option value={WorkCenterStatusEnum.Retired}>Emekli</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
@ -265,10 +267,11 @@ const NewWorkCenterModal: React.FC<NewWorkCenterModalProps> = ({ isOpen, onClose
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={CriticalityLevelEnum.Low}>Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Medium}>Orta</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.High}>Yüksek</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.Critical}>Kritik</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -12,6 +12,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
import { mockEmployees } from '../../../mocks/mockEmployees' import { mockEmployees } from '../../../mocks/mockEmployees'
import { mockMaterials } from '../../../mocks/mockMaterials' import { mockMaterials } from '../../../mocks/mockMaterials'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getPriorityText, getWorkOrderTypeText } from '@/utils/erp'
interface NewWorkOrderModalProps { interface NewWorkOrderModalProps {
isOpen: boolean isOpen: boolean
@ -242,11 +243,11 @@ const NewWorkOrderModal: React.FC<NewWorkOrderModalProps> = ({ isOpen, onClose,
} }
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option> {Object.values(WorkOrderTypeEnum).map((type) => (
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option> <option key={type} value={type}>
<option value={WorkOrderTypeEnum.Emergency}>Acil</option> {getWorkOrderTypeText(type)}
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option> </option>
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option> ))}
</select> </select>
</div> </div>
@ -262,10 +263,11 @@ const NewWorkOrderModal: React.FC<NewWorkOrderModalProps> = ({ isOpen, onClose,
} }
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -102,10 +102,11 @@ const StatusUpdateModal: React.FC<StatusUpdateModalProps> = ({
onChange={(e) => setNewStatus(e.target.value as WorkCenterStatusEnum)} onChange={(e) => setNewStatus(e.target.value as WorkCenterStatusEnum)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option> {Object.values(WorkCenterStatusEnum).map((status) => (
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option> <option key={status} value={status}>
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option> {getWorkCenterStatusText(status)}
<option value={WorkCenterStatusEnum.Retired}>Emekli</option> </option>
))}
</select> </select>
{isStatusCritical && ( {isStatusCritical && (
@ -145,10 +146,11 @@ const StatusUpdateModal: React.FC<StatusUpdateModalProps> = ({
onChange={(e) => setNewCriticality(e.target.value as CriticalityLevelEnum)} onChange={(e) => setNewCriticality(e.target.value as CriticalityLevelEnum)}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value={CriticalityLevelEnum.Low}>Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Medium}>Orta</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.High}>Yüksek</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.Critical}>Kritik</option> </option>
))}
</select> </select>
</div> </div>
)} )}

View file

@ -238,10 +238,11 @@ const WorkCenterCards: React.FC = () => {
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option> {Object.values(WorkCenterStatusEnum).map((status) => (
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option> <option key={status} value={status}>
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option> {getWorkCenterStatusText(status)}
<option value={WorkCenterStatusEnum.Retired}>Emekli</option> </option>
))}
</select> </select>
</div> </div>
<div className="relative"> <div className="relative">
@ -250,11 +251,11 @@ const WorkCenterCards: React.FC = () => {
onChange={(e) => setCriticalityFilter(e.target.value as CriticalityLevelEnum | 'all')} onChange={(e) => setCriticalityFilter(e.target.value as CriticalityLevelEnum | 'all')}
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Kritiklik</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Low}>Düşük</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.Medium}>Orta</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.High}>Yüksek</option> </option>
<option value={CriticalityLevelEnum.Critical}>Kritik</option> ))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -21,6 +21,7 @@ import { mockDepartments } from '../../../mocks/mockDepartments'
import { HrDepartment } from '../../../types/hr' import { HrDepartment } from '../../../types/hr'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
interface ValidationErrors { interface ValidationErrors {
[key: string]: string [key: string]: string
@ -65,7 +66,7 @@ const WorkCenterForm: React.FC = () => {
capacity: 0, capacity: 0,
costPerHour: 0, costPerHour: 0,
setupTime: 0, setupTime: 0,
machineType: '', machineTypeId: '',
isActive: true, isActive: true,
creationTime: new Date('2022-03-15'), creationTime: new Date('2022-03-15'),
lastModificationTime: new Date('2024-01-15'), lastModificationTime: new Date('2024-01-15'),
@ -288,12 +289,11 @@ const WorkCenterForm: React.FC = () => {
}`} }`}
> >
<option value="">Tip seçin</option> <option value="">Tip seçin</option>
<option value="MACHINE">Makine</option> {mockWorkCenters.map((wc) => (
<option value="VEHICLE">Araç</option> <option key={wc.workCenterType?.id} value={wc.workCenterType?.id}>
<option value="TOOL">Alet</option> {wc.workCenterType?.code} - {wc.workCenterType?.name}
<option value="FACILITY">Tesis</option> </option>
<option value="SYSTEM">Sistem</option> ))}
<option value="OTHER">Diğer</option>
</select> </select>
{errors.workCenterType && ( {errors.workCenterType && (
<p className="mt-1 text-sm text-red-600">{errors.workCenterType}</p> <p className="mt-1 text-sm text-red-600">{errors.workCenterType}</p>
@ -428,10 +428,11 @@ const WorkCenterForm: React.FC = () => {
onChange={(e) => handleInputChange('status', e.target.value)} onChange={(e) => handleInputChange('status', e.target.value)}
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="OPERATIONAL">Çalışır Durumda</option> {Object.values(WorkCenterStatusEnum).map((status) => (
<option value="DOWN">Arızalı</option> <option key={status} value={status}>
<option value="MAINTENANCE">Bakımda</option> {getWorkCenterStatusText(status)}
<option value="RETIRED">Kullanım Dışı</option> </option>
))}
</select> </select>
</div> </div>
@ -444,10 +445,11 @@ const WorkCenterForm: React.FC = () => {
onChange={(e) => handleInputChange('criticality', e.target.value)} onChange={(e) => handleInputChange('criticality', e.target.value)}
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500" className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
> >
<option value="LOW">Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value="MEDIUM">Orta</option> <option key={level} value={level}>
<option value="HIGH">Yüksek</option> {getCriticalityLevelText(level)}
<option value="CRITICAL">Kritik</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -141,10 +141,11 @@ const WorkCenterList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option> {Object.values(WorkCenterStatusEnum).map((status) => (
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option> <option key={status} value={status}>
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option> {getWorkCenterStatusText(status)}
<option value={WorkCenterStatusEnum.Retired}>Emekli</option> </option>
))}
</select> </select>
</div> </div>
@ -156,10 +157,11 @@ const WorkCenterList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={CriticalityLevelEnum.Low}>Düşük</option> {Object.values(CriticalityLevelEnum).map((level) => (
<option value={CriticalityLevelEnum.Medium}>Orta</option> <option key={level} value={level}>
<option value={CriticalityLevelEnum.High}>Yüksek</option> {getCriticalityLevelText(level)}
<option value={CriticalityLevelEnum.Critical}>Kritik</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -13,7 +13,7 @@ import {
} from 'react-icons/fa' } from 'react-icons/fa'
import { MrpBOM, MrpBOMComponent, MrpBOMOperation } from '../../../types/mrp' import { MrpBOM, MrpBOMComponent, MrpBOMOperation } from '../../../types/mrp'
import BOMFormModal from './BOMFormModal' import BOMFormModal from './BOMFormModal'
import { getBOMTypeColor, getBOMTypeName } from '../../../utils/erp' import { getBOMTypeColor, getBOMTypeText } from '../../../utils/erp'
import { mockBOMs } from '../../../mocks/mockBOMs' import { mockBOMs } from '../../../mocks/mockBOMs'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
@ -82,9 +82,7 @@ const BOMManagement: React.FC = () => {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<h2 className="text-2xl font-bold text-gray-900">Ürün Ağaçları (BOM)</h2> <h2 className="text-2xl font-bold text-gray-900">Ürün Ağaçları (BOM)</h2>
<p className="text-gray-600"> <p className="text-gray-600">Ürün bileşenlerini ve üretim operasyonlarını yönetin</p>
Ürün bileşenlerini ve üretim operasyonlarını yönetin
</p>
</div> </div>
<button <button
onClick={handleAddNew} onClick={handleAddNew}
@ -126,7 +124,7 @@ const BOMManagement: React.FC = () => {
bom.bomType, bom.bomType,
)}`} )}`}
> >
{getBOMTypeName(bom.bomType)} {getBOMTypeText(bom.bomType)}
</span> </span>
</div> </div>
<p className="text-sm text-gray-600 mb-0.5"> <p className="text-sm text-gray-600 mb-0.5">
@ -235,7 +233,7 @@ const BOMManagement: React.FC = () => {
Malzeme: {selectedBOM.material?.code} - {selectedBOM.material?.name} Malzeme: {selectedBOM.material?.code} - {selectedBOM.material?.name}
</div> </div>
<div>Versiyon: {selectedBOM.version}</div> <div>Versiyon: {selectedBOM.version}</div>
<div>Tip: {getBOMTypeName(selectedBOM.bomType)}</div> <div>Tip: {getBOMTypeText(selectedBOM.bomType)}</div>
<div>Temel Miktar: {selectedBOM.baseQuantity}</div> <div>Temel Miktar: {selectedBOM.baseQuantity}</div>
</div> </div>
</div> </div>

View file

@ -1,15 +1,14 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaTimes, FaSave } from "react-icons/fa"; import { FaTimes, FaSave } from 'react-icons/fa'
import { MrpDemandForecast, ForecastMethodEnum } from "../../../types/mrp"; import { MrpDemandForecast, ForecastMethodEnum } from '../../../types/mrp'
import { mockMaterials } from "../../../mocks/mockMaterials"; import { mockMaterials } from '../../../mocks/mockMaterials'
import { getForecastMethodText } from '@/utils/erp'
interface DemandForecastFormModalProps { interface DemandForecastFormModalProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: ( onSave: (forecastData: Omit<MrpDemandForecast, 'id' | 'material'> & { id?: string }) => void
forecastData: Omit<MrpDemandForecast, "id" | "material"> & { id?: string } initialData: MrpDemandForecast | null
) => void;
initialData: MrpDemandForecast | null;
} }
const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
@ -19,9 +18,9 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
initialData, initialData,
}) => { }) => {
const newFormData: MrpDemandForecast = { const newFormData: MrpDemandForecast = {
id: "", id: '',
materialId: "", materialId: '',
forecastPeriod: "", forecastPeriod: '',
startDate: new Date(), startDate: new Date(),
endDate: new Date(), endDate: new Date(),
forecastMethod: ForecastMethodEnum.MovingAverage, forecastMethod: ForecastMethodEnum.MovingAverage,
@ -32,10 +31,10 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
trendFactor: 0, trendFactor: 0,
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
notes: "", notes: '',
}; }
const [formData, setFormData] = useState(newFormData); const [formData, setFormData] = useState(newFormData)
useEffect(() => { useEffect(() => {
if (initialData) { if (initialData) {
@ -43,36 +42,33 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
...initialData, ...initialData,
startDate: new Date(initialData.startDate), startDate: new Date(initialData.startDate),
endDate: new Date(initialData.endDate), endDate: new Date(initialData.endDate),
}); })
} else { } else {
setFormData(newFormData); setFormData(newFormData)
} }
}, [initialData, isOpen]); }, [initialData, isOpen])
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
const saveData = { const saveData = {
...formData, ...formData,
id: initialData?.id, id: initialData?.id,
startDate: new Date(formData.startDate), startDate: new Date(formData.startDate),
endDate: new Date(formData.endDate), endDate: new Date(formData.endDate),
}; }
onSave(saveData); onSave(saveData)
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{initialData ? "Talep Tahmini Düzenle" : "Yeni Talep Tahmini"} {initialData ? 'Talep Tahmini Düzenle' : 'Yeni Talep Tahmini'}
</h2> </h2>
<button <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
onClick={onClose}
className="text-gray-400 hover:text-gray-600"
>
<FaTimes className="w-4 h-4" /> <FaTimes className="w-4 h-4" />
</button> </button>
</div> </div>
@ -80,15 +76,11 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
<form onSubmit={handleSubmit} className="p-4 space-y-4"> <form onSubmit={handleSubmit} className="p-4 space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Malzeme</label>
Malzeme
</label>
<select <select
required required
value={formData.materialId} value={formData.materialId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, materialId: e.target.value })}
setFormData({ ...formData, materialId: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Seçiniz</option> <option value="">Seçiniz</option>
@ -108,9 +100,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
type="text" type="text"
required required
value={formData.forecastPeriod} value={formData.forecastPeriod}
onChange={(e) => onChange={(e) => setFormData({ ...formData, forecastPeriod: e.target.value })}
setFormData({ ...formData, forecastPeriod: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Örn: 2024-Q3" placeholder="Örn: 2024-Q3"
/> />
@ -123,7 +113,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
<input <input
type="date" type="date"
required required
value={formData.startDate.toISOString().split("T")[0]} value={formData.startDate.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -135,13 +125,11 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Bitiş Tarihi</label>
Bitiş Tarihi
</label>
<input <input
type="date" type="date"
required required
value={formData.endDate.toISOString().split("T")[0]} value={formData.endDate.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -153,9 +141,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Tahmin Yöntemi</label>
Tahmin Yöntemi
</label>
<select <select
required required
value={formData.forecastMethod} value={formData.forecastMethod}
@ -167,23 +153,16 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
} }
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={ForecastMethodEnum.MovingAverage}> {Object.values(ForecastMethodEnum).map((method) => (
Hareketli Ortalama <option key={method} value={method}>
</option> {getForecastMethodText(method)}
<option value={ForecastMethodEnum.ExponentialSmoothing}> </option>
Üstel Yumuşatma ))}
</option>
<option value={ForecastMethodEnum.LinearRegression}>
Doğrusal Regresyon
</option>
<option value={ForecastMethodEnum.Seasonal}>Mevsimsel</option>
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">Tahmin Miktarı</label>
Tahmin Miktarı
</label>
<input <input
type="number" type="number"
required required
@ -219,7 +198,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default DemandForecastFormModal; export default DemandForecastFormModal

View file

@ -1,17 +1,18 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaTimes, FaSave } from "react-icons/fa"; import { FaTimes, FaSave } from 'react-icons/fa'
import { MrpWorkOrder } from "../../../types/mrp"; import { MrpWorkOrder } from '../../../types/mrp'
import { mockProductionOrders } from "../../../mocks/mockProductionOrders"; import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
import { mockOperations } from "../../../mocks/mockOperations"; import { mockOperations } from '../../../mocks/mockOperations'
import { mockMaterials } from "../../../mocks/mockMaterials"; import { mockMaterials } from '../../../mocks/mockMaterials'
import { mockWorkCenters } from "../../../mocks/mockWorkCenters"; import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { WorkOrderStatusEnum } from "../../../types/pm"; import { WorkOrderStatusEnum } from '../../../types/pm'
import { getWorkOrderStatusText } from '@/utils/erp'
interface EditWorkOrderFormProps { interface EditWorkOrderFormProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: (workOrder: MrpWorkOrder) => void; onSave: (workOrder: MrpWorkOrder) => void
workOrder: MrpWorkOrder | null; workOrder: MrpWorkOrder | null
} }
const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
@ -21,20 +22,20 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
workOrder, workOrder,
}) => { }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
workOrderNumber: "", workOrderNumber: '',
productionOrderId: "", productionOrderId: '',
operationId: "", operationId: '',
materialId: "", materialId: '',
sequence: 1, sequence: 1,
plannedStartDate: "", plannedStartDate: '',
plannedEndDate: "", plannedEndDate: '',
plannedQuantity: 0, plannedQuantity: 0,
workCenterId: "", workCenterId: '',
assignedOperators: [] as string[], assignedOperators: [] as string[],
setupTime: 0, setupTime: 0,
processTime: 0, processTime: 0,
status: WorkOrderStatusEnum.Created, status: WorkOrderStatusEnum.Created,
}); })
useEffect(() => { useEffect(() => {
if (workOrder) { if (workOrder) {
@ -44,23 +45,21 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
operationId: workOrder.operationId, operationId: workOrder.operationId,
materialId: workOrder.materialId, materialId: workOrder.materialId,
sequence: workOrder.sequence, sequence: workOrder.sequence,
plannedStartDate: workOrder.plannedStartDate plannedStartDate: workOrder.plannedStartDate.toISOString().split('T')[0],
.toISOString() plannedEndDate: workOrder.plannedEndDate.toISOString().split('T')[0],
.split("T")[0],
plannedEndDate: workOrder.plannedEndDate.toISOString().split("T")[0],
plannedQuantity: workOrder.plannedQuantity, plannedQuantity: workOrder.plannedQuantity,
workCenterId: workOrder.workCenterId, workCenterId: workOrder.workCenterId,
assignedOperators: workOrder.assignedOperators, assignedOperators: workOrder.assignedOperators,
setupTime: workOrder.setupTime, setupTime: workOrder.setupTime,
processTime: workOrder.processTime, processTime: workOrder.processTime,
status: workOrder.status, status: workOrder.status,
}); })
} }
}, [workOrder]); }, [workOrder])
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (!workOrder) return; if (!workOrder) return
const updatedWorkOrder: MrpWorkOrder = { const updatedWorkOrder: MrpWorkOrder = {
...workOrder, ...workOrder,
@ -68,24 +67,19 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
plannedStartDate: new Date(formData.plannedStartDate), plannedStartDate: new Date(formData.plannedStartDate),
plannedEndDate: new Date(formData.plannedEndDate), plannedEndDate: new Date(formData.plannedEndDate),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}; }
onSave(updatedWorkOrder); onSave(updatedWorkOrder)
onClose(); onClose()
}; }
if (!isOpen || !workOrder) return null; if (!isOpen || !workOrder) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">İş Emri Düzenle</h2>
İş Emri Düzenle <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
</h2>
<button
onClick={onClose}
className="text-gray-400 hover:text-gray-600"
>
<FaTimes className="w-4 h-4" /> <FaTimes className="w-4 h-4" />
</button> </button>
</div> </div>
@ -100,18 +94,14 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
type="text" type="text"
required required
value={formData.workOrderNumber} value={formData.workOrderNumber}
onChange={(e) => onChange={(e) => setFormData({ ...formData, workOrderNumber: e.target.value })}
setFormData({ ...formData, workOrderNumber: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="WO-2024-XXX" placeholder="WO-2024-XXX"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Üretim Emri</label>
Üretim Emri
</label>
<select <select
required required
value={formData.productionOrderId} value={formData.productionOrderId}
@ -133,15 +123,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Operasyon</label>
Operasyon
</label>
<select <select
required required
value={formData.operationId} value={formData.operationId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, operationId: e.target.value })}
setFormData({ ...formData, operationId: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Seçiniz</option> <option value="">Seçiniz</option>
@ -154,15 +140,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Malzeme</label>
Malzeme
</label>
<select <select
required required
value={formData.materialId} value={formData.materialId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, materialId: e.target.value })}
setFormData({ ...formData, materialId: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Seçiniz</option> <option value="">Seçiniz</option>
@ -175,15 +157,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">İş Merkezi</label>
İş Merkezi
</label>
<select <select
required required
value={formData.workCenterId} value={formData.workCenterId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, workCenterId: e.target.value })}
setFormData({ ...formData, workCenterId: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Seçiniz</option> <option value="">Seçiniz</option>
@ -196,9 +174,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Sıra</label>
Sıra
</label>
<input <input
type="number" type="number"
required required
@ -222,9 +198,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
type="date" type="date"
required required
value={formData.plannedStartDate} value={formData.plannedStartDate}
onChange={(e) => onChange={(e) => setFormData({ ...formData, plannedStartDate: e.target.value })}
setFormData({ ...formData, plannedStartDate: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
@ -237,9 +211,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
type="date" type="date"
required required
value={formData.plannedEndDate} value={formData.plannedEndDate}
onChange={(e) => onChange={(e) => setFormData({ ...formData, plannedEndDate: e.target.value })}
setFormData({ ...formData, plannedEndDate: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>
@ -302,9 +274,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
Durum
</label>
<select <select
value={formData.status} value={formData.status}
onChange={(e) => onChange={(e) =>
@ -315,15 +285,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
} }
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option> {Object.values(WorkOrderStatusEnum).map((status) => (
<option value={WorkOrderStatusEnum.Released}>Yayınlandı</option> <option key={status} value={status}>
<option value={WorkOrderStatusEnum.InProgress}>İşlemde</option> {getWorkOrderStatusText(status)}
<option value={WorkOrderStatusEnum.Completed}> </option>
Tamamlandı ))}
</option>
<option value={WorkOrderStatusEnum.Cancelled}>
İptal Edildi
</option>
</select> </select>
</div> </div>
</div> </div>
@ -347,7 +313,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default EditWorkOrderForm; export default EditWorkOrderForm

View file

@ -1,25 +1,24 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaTimes, FaSave } from "react-icons/fa"; import { FaTimes, FaSave } from 'react-icons/fa'
import { import { MrpMaterialRequirement, RequirementSourceTypeEnum } from '../../../types/mrp'
MrpMaterialRequirement, import { mockMaterials } from '../../../mocks/mockMaterials'
RequirementSourceTypeEnum, import { getRequirementSourceTypeText } from '@/utils/erp'
} from "../../../types/mrp";
import { mockMaterials } from "../../../mocks/mockMaterials";
interface MaterialRequirementFormModalProps { interface MaterialRequirementFormModalProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
onSave: ( onSave: (reqData: Omit<MrpMaterialRequirement, 'id' | 'material'> & { id?: string }) => void
reqData: Omit<MrpMaterialRequirement, "id" | "material"> & { id?: string } initialData: MrpMaterialRequirement | null
) => void;
initialData: MrpMaterialRequirement | null;
} }
const MaterialRequirementFormModal: React.FC< const MaterialRequirementFormModal: React.FC<MaterialRequirementFormModalProps> = ({
MaterialRequirementFormModalProps isOpen,
> = ({ isOpen, onClose, onSave, initialData }) => { onClose,
onSave,
initialData,
}) => {
const newFormData: MrpMaterialRequirement = { const newFormData: MrpMaterialRequirement = {
materialId: "", materialId: '',
sourceType: RequirementSourceTypeEnum.Forecast, sourceType: RequirementSourceTypeEnum.Forecast,
grossRequirement: 0, grossRequirement: 0,
netRequirement: 0, netRequirement: 0,
@ -29,14 +28,14 @@ const MaterialRequirementFormModal: React.FC<
plannedOrderRelease: 0, plannedOrderRelease: 0,
requirementDate: new Date(), requirementDate: new Date(),
plannedReceiptDate: new Date(), plannedReceiptDate: new Date(),
id: "", id: '',
mrpRunId: "", mrpRunId: '',
plannedReleaseDate: new Date(), plannedReleaseDate: new Date(),
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
}; }
const [formData, setFormData] = useState(newFormData); const [formData, setFormData] = useState(newFormData)
useEffect(() => { useEffect(() => {
if (initialData) { if (initialData) {
@ -44,37 +43,34 @@ const MaterialRequirementFormModal: React.FC<
...initialData, ...initialData,
requirementDate: new Date(initialData.requirementDate), requirementDate: new Date(initialData.requirementDate),
plannedReceiptDate: new Date(initialData.plannedReceiptDate), plannedReceiptDate: new Date(initialData.plannedReceiptDate),
}); })
} else { } else {
// Reset form for new entry // Reset form for new entry
setFormData(newFormData); setFormData(newFormData)
} }
}, [initialData, isOpen]); }, [initialData, isOpen])
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
const saveData = { const saveData = {
...formData, ...formData,
id: initialData?.id, id: initialData?.id,
requirementDate: new Date(formData.requirementDate), requirementDate: new Date(formData.requirementDate),
plannedReceiptDate: new Date(formData.plannedReceiptDate), plannedReceiptDate: new Date(formData.plannedReceiptDate),
}; }
onSave(saveData); onSave(saveData)
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<h2 className="text-lg font-semibold text-gray-900"> <h2 className="text-lg font-semibold text-gray-900">
{initialData ? "Malzeme İhtiyacı Düzenle" : "Yeni Malzeme İhtiyacı"} {initialData ? 'Malzeme İhtiyacı Düzenle' : 'Yeni Malzeme İhtiyacı'}
</h2> </h2>
<button <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
onClick={onClose}
className="text-gray-400 hover:text-gray-600"
>
<FaTimes className="w-4 h-4" /> <FaTimes className="w-4 h-4" />
</button> </button>
</div> </div>
@ -82,15 +78,11 @@ const MaterialRequirementFormModal: React.FC<
<form onSubmit={handleSubmit} className="p-4 space-y-4"> <form onSubmit={handleSubmit} className="p-4 space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Malzeme</label>
Malzeme
</label>
<select <select
required required
value={formData.materialId} value={formData.materialId}
onChange={(e) => onChange={(e) => setFormData({ ...formData, materialId: e.target.value })}
setFormData({ ...formData, materialId: e.target.value })
}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="">Seçiniz</option> <option value="">Seçiniz</option>
@ -103,9 +95,7 @@ const MaterialRequirementFormModal: React.FC<
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Kaynak Tipi</label>
Kaynak Tipi
</label>
<select <select
required required
value={formData.sourceType} value={formData.sourceType}
@ -117,25 +107,16 @@ const MaterialRequirementFormModal: React.FC<
} }
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value={RequirementSourceTypeEnum.Forecast}> {Object.values(RequirementSourceTypeEnum).map((type) => (
Tahmin <option key={type} value={type}>
</option> {getRequirementSourceTypeText(type)}
<option value={RequirementSourceTypeEnum.SalesOrder}> </option>
Satış Siparişi ))}
</option>
<option value={RequirementSourceTypeEnum.SafetyStock}>
Güvenlik Stoku
</option>
<option value={RequirementSourceTypeEnum.ProductionOrder}>
Üretim Emri
</option>
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Brüt İhtiyaç</label>
Brüt İhtiyaç
</label>
<input <input
type="number" type="number"
required required
@ -152,9 +133,7 @@ const MaterialRequirementFormModal: React.FC<
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Net İhtiyaç</label>
Net İhtiyaç
</label>
<input <input
type="number" type="number"
required required
@ -170,13 +149,11 @@ const MaterialRequirementFormModal: React.FC<
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">İhtiyaç Tarihi</label>
İhtiyaç Tarihi
</label>
<input <input
type="date" type="date"
required required
value={formData.requirementDate.toISOString().split("T")[0]} value={formData.requirementDate.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -194,7 +171,7 @@ const MaterialRequirementFormModal: React.FC<
<input <input
type="date" type="date"
required required
value={formData.plannedReceiptDate.toISOString().split("T")[0]} value={formData.plannedReceiptDate.toISOString().split('T')[0]}
onChange={(e) => onChange={(e) =>
setFormData({ setFormData({
...formData, ...formData,
@ -225,7 +202,7 @@ const MaterialRequirementFormModal: React.FC<
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default MaterialRequirementFormModal; export default MaterialRequirementFormModal

View file

@ -1,15 +1,13 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { FaSave, FaTimes } from "react-icons/fa"; import { FaSave, FaTimes } from 'react-icons/fa'
import { import { OperationCategoryEnum, MrpOperationTypeDefinition } from '../../../types/mrp'
OperationCategoryEnum, import { getOperationTypeText } from '@/utils/erp'
MrpOperationTypeDefinition,
} from "../../../types/mrp";
interface OperationTypeFormProps { interface OperationTypeFormProps {
open: boolean; open: boolean
initial?: MrpOperationTypeDefinition | null; initial?: MrpOperationTypeDefinition | null
onClose: () => void; onClose: () => void
onSave: (data: MrpOperationTypeDefinition) => void; onSave: (data: MrpOperationTypeDefinition) => void
} }
const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
@ -18,13 +16,13 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
onClose, onClose,
onSave, onSave,
}) => { }) => {
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false)
const [form, setForm] = useState<MrpOperationTypeDefinition>( const [form, setForm] = useState<MrpOperationTypeDefinition>(
initial || { initial || {
id: "", id: '',
code: "", code: '',
name: "", name: '',
description: "", description: '',
category: OperationCategoryEnum.Setup, category: OperationCategoryEnum.Setup,
defaultDuration: 0, defaultDuration: 0,
requiresSetup: false, requiresSetup: false,
@ -34,85 +32,79 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
isActive: true, isActive: true,
creationTime: new Date(), creationTime: new Date(),
lastModificationTime: new Date(), lastModificationTime: new Date(),
} },
); )
useEffect(() => { useEffect(() => {
if (initial) setForm(initial); if (initial) setForm(initial)
else else
setForm((prev) => ({ setForm((prev) => ({
...prev, ...prev,
id: "", id: '',
code: "", code: '',
name: "", name: '',
description: "", description: '',
})); }))
}, [initial, open]); }, [initial, open])
if (!open) return null; if (!open) return null
const handleChange = ( const handleChange = (
field: keyof MrpOperationTypeDefinition, field: keyof MrpOperationTypeDefinition,
value: string | number | boolean value: string | number | boolean,
) => { ) => {
setForm((s) => ({ setForm((s) => ({
...s, ...s,
[field]: value, [field]: value,
lastModificationTime: new Date(), lastModificationTime: new Date(),
})); }))
}; }
const handleSave = async () => { const handleSave = async () => {
setSaving(true); setSaving(true)
try { try {
// simulate API // simulate API
await new Promise((r) => setTimeout(r, 600)); await new Promise((r) => setTimeout(r, 600))
onSave({ ...form, id: form.id || String(Date.now()) }); onSave({ ...form, id: form.id || String(Date.now()) })
} finally { } finally {
setSaving(false); setSaving(false)
} }
}; }
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-4 w-full max-w-xl mx-4"> <div className="bg-white rounded-lg p-4 w-full max-w-xl mx-4">
<h3 className="text-lg font-semibold mb-3"> <h3 className="text-lg font-semibold mb-3">
{form.id ? "Operasyon Türünü Düzenle" : "Yeni Operasyon Türü"} {form.id ? 'Operasyon Türünü Düzenle' : 'Yeni Operasyon Türü'}
</h3> </h3>
<div className="space-y-2"> <div className="space-y-2">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Kod</label>
Kod
</label>
<input <input
autoFocus autoFocus
value={form.code} value={form.code}
onChange={(e) => handleChange("code", e.target.value)} onChange={(e) => handleChange('code', e.target.value)}
className="w-full border rounded-lg px-2 py-1.5 text-sm" className="w-full border rounded-lg px-2 py-1.5 text-sm"
placeholder="Örn: CUT001" placeholder="Örn: CUT001"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Ad</label>
Ad
</label>
<input <input
value={form.name} value={form.name}
onChange={(e) => handleChange("name", e.target.value)} onChange={(e) => handleChange('name', e.target.value)}
className="w-full border rounded-lg px-2 py-1.5 text-sm" className="w-full border rounded-lg px-2 py-1.5 text-sm"
placeholder="Kesme İşlemi" placeholder="Kesme İşlemi"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">ıklama</label>
ıklama
</label>
<textarea <textarea
value={form.description} value={form.description}
onChange={(e) => handleChange("description", e.target.value)} onChange={(e) => handleChange('description', e.target.value)}
rows={3} rows={3}
className="w-full border rounded-lg px-2 py-1.5 text-sm" className="w-full border rounded-lg px-2 py-1.5 text-sm"
/> />
@ -120,27 +112,18 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Kategori</label>
Kategori
</label>
<select <select
value={form.category} value={form.category}
onChange={(e) => handleChange("category", e.target.value)} onChange={(e) => handleChange('category', e.target.value)}
className="w-full border rounded-lg px-2 py-1.5 text-sm" className="w-full border rounded-lg px-2 py-1.5 text-sm"
> >
<option value="">Kategori seçin</option> <option value="">Kategori seçin</option>
<option value={OperationCategoryEnum.Production}>Üretim</option> {Object.values(OperationCategoryEnum).map((cat) => (
<option value={OperationCategoryEnum.Assembly}>Montaj</option> <option key={cat} value={cat}>
<option value={OperationCategoryEnum.Inspection}> {getOperationTypeText(cat)}
Kontrol </option>
</option> ))}
<option value={OperationCategoryEnum.Packaging}>
Paketleme
</option>
<option value={OperationCategoryEnum.Setup}>Hazırlık</option>
<option value={OperationCategoryEnum.Maintenance}>Bakım</option>
<option value={OperationCategoryEnum.Transport}>Taşıma</option>
<option value={OperationCategoryEnum.Quality}>Kalite</option>
</select> </select>
</div> </div>
<div> <div>
@ -150,9 +133,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
<input <input
type="number" type="number"
value={form.defaultDuration} value={form.defaultDuration}
onChange={(e) => onChange={(e) => handleChange('defaultDuration', Number(e.target.value))}
handleChange("defaultDuration", Number(e.target.value))
}
className="w-full border rounded-lg px-2 py-1.5 text-sm" className="w-full border rounded-lg px-2 py-1.5 text-sm"
/> />
</div> </div>
@ -163,9 +144,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
<input <input
type="checkbox" type="checkbox"
checked={form.requiresSetup} checked={form.requiresSetup}
onChange={(e) => onChange={(e) => handleChange('requiresSetup', e.target.checked)}
handleChange("requiresSetup", e.target.checked)
}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/> />
<span className="text-sm text-gray-700">Hazırlık Gerekli</span> <span className="text-sm text-gray-700">Hazırlık Gerekli</span>
@ -175,9 +154,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
<input <input
type="checkbox" type="checkbox"
checked={form.allowsParallelOperation} checked={form.allowsParallelOperation}
onChange={(e) => onChange={(e) => handleChange('allowsParallelOperation', e.target.checked)}
handleChange("allowsParallelOperation", e.target.checked)
}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/> />
<span className="text-sm text-gray-700">Paralel İşlem</span> <span className="text-sm text-gray-700">Paralel İşlem</span>
@ -197,13 +174,12 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
disabled={saving} disabled={saving}
className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-400" className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-400"
> >
<FaSave className="inline mr-2" />{" "} <FaSave className="inline mr-2" /> {saving ? 'Kaydediliyor...' : 'Kaydet'}
{saving ? "Kaydediliyor..." : "Kaydet"}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
); )
}; }
export default OperationTypeFormModal; export default OperationTypeFormModal

View file

@ -13,12 +13,7 @@ import {
import { MrpOperationTypeDefinition } from '../../../types/mrp' import { MrpOperationTypeDefinition } from '../../../types/mrp'
import OperationTypeFormModal from './OperationTypeFormModal' import OperationTypeFormModal from './OperationTypeFormModal'
import { mockOperationTypes } from '../../../mocks/mockOperationTypes' import { mockOperationTypes } from '../../../mocks/mockOperationTypes'
import { import { getOperationTypeColor, getOperationTypeText, getSkillLevelText } from '../../../utils/erp'
getOperationCategoryColor,
getOperationTypeColor,
getOperationTypeText,
getSkillLevelText,
} from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
const OperationTypes: React.FC = () => { const OperationTypes: React.FC = () => {
@ -261,7 +256,7 @@ const OperationTypes: React.FC = () => {
</td> </td>
<td className="px-3 py-2 whitespace-nowrap"> <td className="px-3 py-2 whitespace-nowrap">
<span <span
className={`px-2 py-1 rounded-full text-xs font-medium ${getOperationCategoryColor( className={`px-2 py-1 rounded-full text-xs font-medium ${getOperationTypeText(
type.category, type.category,
)}`} )}`}
> >

View file

@ -11,9 +11,9 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
import { mockProductionOrders } from '../../../mocks/mockProductionOrders' import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
import { mockWorkOrders } from '../../../mocks/mockWorkOrders' import { mockWorkOrders } from '../../../mocks/mockWorkOrders'
import { mockWorkCenters } from '../../../mocks/mockWorkCenters' import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
import { PriorityEnum } from '../../../types/common' import { getFrequencyUnitText, getPriorityColor } from '../../../utils/erp'
import { getPriorityColor, getProductionOrderStatus, getWorkOrderStatus } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { FrequencyUnitEnum } from '@/types/pm'
interface PlanningGanttProps { interface PlanningGanttProps {
workCenterId?: string workCenterId?: string
@ -107,7 +107,7 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
assignee: wo.assignedOperators[0] assignee: wo.assignedOperators[0]
? mockEmployees.find((e) => e.id === wo.assignedOperators[0]) ? mockEmployees.find((e) => e.id === wo.assignedOperators[0])
: undefined, : undefined,
status: getWorkOrderStatus(wo.status), status: wo.status,
priority: order.priority, priority: order.priority,
level: 1, level: 1,
children: [], children: [],
@ -125,7 +125,7 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
order.confirmedQuantity && order.plannedQuantity order.confirmedQuantity && order.plannedQuantity
? Math.round((order.confirmedQuantity / order.plannedQuantity) * 100) ? Math.round((order.confirmedQuantity / order.plannedQuantity) * 100)
: 0, : 0,
status: getProductionOrderStatus(order.status), status: order.status,
priority: order.priority, priority: order.priority,
level: 0, level: 0,
children: workOrders, children: workOrders,
@ -480,10 +480,18 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')} onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')}
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto" className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto"
> >
<option value="day">Günlük</option> <option value={FrequencyUnitEnum.Days}>
<option value="week">Haftalık</option> {getFrequencyUnitText(FrequencyUnitEnum.Days)}
<option value="month">Aylık</option> </option>
<option value="year">Yıllık</option> <option value={FrequencyUnitEnum.Weeks}>
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
</option>
<option value={FrequencyUnitEnum.Months}>
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
</option>
<option value={FrequencyUnitEnum.Years}>
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
</option>
</select> </select>
</div> </div>
</div> </div>

View file

@ -26,6 +26,12 @@ import { mockMaterials } from '../../../mocks/mockMaterials'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import {
getPriorityText,
getProductionOrderStatusText,
getProductionOrderTypeText,
} from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
const ProductionOrderForm: React.FC = () => { const ProductionOrderForm: React.FC = () => {
const { id } = useParams() const { id } = useParams()
@ -260,10 +266,11 @@ const ProductionOrderForm: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
> >
<option value={ProductionOrderTypeEnum.Standard}>Standart</option> {Object.values(ProductionOrderTypeEnum).map((type) => (
<option value={ProductionOrderTypeEnum.Rework}>Yeniden İşleme</option> <option key={type} value={type}>
<option value={ProductionOrderTypeEnum.Maintenance}>Bakım</option> {getProductionOrderTypeText(type)}
<option value={ProductionOrderTypeEnum.Sample}>Numune</option> </option>
))}
</select> </select>
</div> </div>
@ -275,12 +282,11 @@ const ProductionOrderForm: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
> >
<option value={ProductionOrderStatusEnum.Created}>Oluşturuldu</option> {Object.values(ProductionOrderStatusEnum).map((status) => (
<option value={ProductionOrderStatusEnum.Released}>Yayınlandı</option> <option key={status} value={status}>
<option value={ProductionOrderStatusEnum.InProgress}>İşlemde</option> {getProductionOrderStatusText(status)}
<option value={ProductionOrderStatusEnum.Completed}>Tamamlandı</option> </option>
<option value={ProductionOrderStatusEnum.Cancelled}>İptal Edildi</option> ))}
<option value={ProductionOrderStatusEnum.OnHold}>Beklemede</option>
</select> </select>
</div> </div>
@ -292,10 +298,11 @@ const ProductionOrderForm: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -469,10 +476,11 @@ const ProductionOrderForm: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-yellow-500 transition-all duration-200 bg-gray-50 focus:bg-white" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-yellow-500 transition-all duration-200 bg-gray-50 focus:bg-white"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
<option value="GBP">GBP</option> </option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -665,12 +665,11 @@ const ProductionOrderList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={ProductionOrderStatusEnum.Created}>Oluşturuldu</option> {Object.values(ProductionOrderStatusEnum).map((status) => (
<option value={ProductionOrderStatusEnum.Released}>Serbest Bırakıldı</option> <option key={status} value={status}>
<option value={ProductionOrderStatusEnum.InProgress}>Devam Ediyor</option> {getProductionOrderStatusText(status)}
<option value={ProductionOrderStatusEnum.Completed}>Tamamlandı</option> </option>
<option value={ProductionOrderStatusEnum.OnHold}>Beklemede</option> ))}
<option value={ProductionOrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>
<div> <div>
@ -681,10 +680,11 @@ const ProductionOrderList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>

View file

@ -8,7 +8,7 @@ import {
FaChartBar, FaChartBar,
FaDownload, FaDownload,
} from 'react-icons/fa' } from 'react-icons/fa'
import { PsProjectCostTracking } from '../../../types/ps' import { ProjectCostTrackingStatus, PsProjectCostTracking } from '../../../types/ps'
import { mockProjectCostTracking } from '../../../mocks/mockProjectCostTracking' import { mockProjectCostTracking } from '../../../mocks/mockProjectCostTracking'
import Widget from '../../../components/common/Widget' import Widget from '../../../components/common/Widget'
import { import {
@ -326,10 +326,11 @@ const CostTimeTracking: React.FC = () => {
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="">Tüm Durumlar</option> <option value="">Tüm Durumlar</option>
<option value="ON_TRACK">Planında</option> {Object.values(ProjectCostTrackingStatus).map((status) => (
<option value="AT_RISK">Risk Altında</option> <option key={status} value={status}>
<option value="DELAYED">Gecikmiş</option> {getCostTimeTrackingStatusText(status)}
<option value="COMPLETED">Tamamlandı</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -1,26 +1,22 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { import { FaPlus, FaEdit, FaSave, FaTimesCircle, FaProjectDiagram } from 'react-icons/fa'
FaPlus,
FaEdit,
FaSave,
FaTimesCircle,
FaProjectDiagram,
} from "react-icons/fa";
import { import {
PhaseStatusEnum, PhaseStatusEnum,
PsProjectPhase, PsProjectPhase,
ProjectStatusEnum, ProjectStatusEnum,
} from "../../../types/ps"; PhaseCategoryEnum,
import { mockProjects } from "../../../mocks/mockProjects"; } from '../../../types/ps'
import { mockProjectPhases } from "../../../mocks/mockProjectPhases"; import { mockProjects } from '../../../mocks/mockProjects'
import MultiSelectTeam from "../../../components/common/MultiSelectTeam"; import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
import { getPhaseCategoryText, getPhaseStatusText } from '@/utils/erp'
interface PhaseEditModalProps { interface PhaseEditModalProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
phase?: PsProjectPhase | null; phase?: PsProjectPhase | null
defaultProjectId?: string; defaultProjectId?: string
onSubmit: (data: PsProjectPhase) => void; onSubmit: (data: PsProjectPhase) => void
} }
const PhaseEditModal: React.FC<PhaseEditModalProps> = ({ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
@ -30,14 +26,14 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
defaultProjectId, defaultProjectId,
onSubmit, onSubmit,
}) => { }) => {
const isEdit = Boolean(phase); const isEdit = Boolean(phase)
const ProjectPhaseNew: PsProjectPhase = { const ProjectPhaseNew: PsProjectPhase = {
id: "", id: '',
projectId: defaultProjectId || "", projectId: defaultProjectId || '',
code: "", code: '',
name: "", name: '',
description: "", description: '',
sequence: 0, sequence: 0,
startDate: new Date(), startDate: new Date(),
endDate: new Date(), endDate: new Date(),
@ -52,10 +48,10 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
assignedTeams: [], assignedTeams: [],
deliverables: [], deliverables: [],
risks: [], risks: [],
category: "", category: PhaseCategoryEnum.Planning,
}; }
const [formData, setFormData] = useState<PsProjectPhase>(ProjectPhaseNew); const [formData, setFormData] = useState<PsProjectPhase>(ProjectPhaseNew)
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {
@ -66,50 +62,48 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
name: phase.name, name: phase.name,
projectId: phase.projectId, projectId: phase.projectId,
code: phase.code, code: phase.code,
description: phase.description || "", description: phase.description || '',
status: phase.status, status: phase.status,
startDate: phase.startDate, startDate: phase.startDate,
endDate: phase.endDate, endDate: phase.endDate,
budget: phase.budget, budget: phase.budget,
category: phase.category, category: phase.category,
assignedTeams: phase.assignedTeams || [], assignedTeams: phase.assignedTeams || [],
}); })
} else { } else {
setFormData(ProjectPhaseNew); setFormData(ProjectPhaseNew)
} }
} }
}, [isOpen, phase, defaultProjectId]); }, [isOpen, phase, defaultProjectId])
const handleInputChange = ( const handleInputChange = (
e: React.ChangeEvent< e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
>
) => { ) => {
const { name, value } = e.target; const { name, value } = e.target
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: value, [name]: value,
})); }))
}; }
const handleTeamChange = (teams: string[]) => { const handleTeamChange = (teams: string[]) => {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
assignedTeams: teams, assignedTeams: teams,
})); }))
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
onSubmit(formData); onSubmit(formData)
}; }
const generatePhaseCode = () => { const generatePhaseCode = () => {
const phaseCount = mockProjectPhases.length + 1; const phaseCount = mockProjectPhases.length + 1
return `PH-${phaseCount.toString().padStart(3, "0")}`; return `PH-${phaseCount.toString().padStart(3, '0')}`
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
@ -126,12 +120,12 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
</div> </div>
<div> <div>
<h3 className="text-base font-semibold text-gray-900"> <h3 className="text-base font-semibold text-gray-900">
{isEdit ? "Aşama Düzenle" : "Yeni Aşama Oluştur"} {isEdit ? 'Aşama Düzenle' : 'Yeni Aşama Oluştur'}
</h3> </h3>
<p className="text-xs text-gray-600"> <p className="text-xs text-gray-600">
{isEdit {isEdit
? "Mevcut aşama bilgilerini güncelleyin" ? 'Mevcut aşama bilgilerini güncelleyin'
: "Yeni bir proje aşaması tanımlayın"} : 'Yeni bir proje aşaması tanımlayın'}
</p> </p>
</div> </div>
</div> </div>
@ -179,9 +173,9 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
{formData.projectId && {formData.projectId &&
(() => { (() => {
const selectedProject = mockProjects.find( const selectedProject = mockProjects.find(
(p) => p.id === formData.projectId (p) => p.id === formData.projectId,
); )
if (!selectedProject) return null; if (!selectedProject) return null
return ( return (
<div className="mt-1.5 p-1.5 bg-blue-50 border border-blue-200 rounded-lg"> <div className="mt-1.5 p-1.5 bg-blue-50 border border-blue-200 rounded-lg">
@ -195,79 +189,56 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
</p> </p>
<div className="grid grid-cols-2 gap-1.5 text-xs"> <div className="grid grid-cols-2 gap-1.5 text-xs">
<div> <div>
<span className="font-medium text-blue-800"> <span className="font-medium text-blue-800">Durum:</span>
Durum:
</span>
<span <span
className={`ml-1 px-1.5 py-0.5 rounded-full text-xs font-medium ${ className={`ml-1 px-1.5 py-0.5 rounded-full text-xs font-medium ${
selectedProject.status === selectedProject.status === ProjectStatusEnum.Active
ProjectStatusEnum.Active ? 'bg-green-100 text-green-800'
? "bg-green-100 text-green-800" : selectedProject.status === ProjectStatusEnum.Planning
: selectedProject.status === ? 'bg-yellow-100 text-yellow-800'
ProjectStatusEnum.Planning : 'bg-gray-100 text-gray-800'
? "bg-yellow-100 text-yellow-800"
: "bg-gray-100 text-gray-800"
}`} }`}
> >
{selectedProject.status === {selectedProject.status === ProjectStatusEnum.Active
ProjectStatusEnum.Active ? 'Aktif'
? "Aktif" : selectedProject.status === ProjectStatusEnum.Planning
: selectedProject.status === ? 'Planlama'
ProjectStatusEnum.Planning : selectedProject.status === ProjectStatusEnum.Completed
? "Planlama" ? 'Tamamlandı'
: selectedProject.status === : selectedProject.status === ProjectStatusEnum.OnHold
ProjectStatusEnum.Completed ? 'Beklemede'
? "Tamamlandı" : 'İptal'}
: selectedProject.status ===
ProjectStatusEnum.OnHold
? "Beklemede"
: "İptal"}
</span> </span>
</div> </div>
<div> <div>
<span className="font-medium text-blue-800"> <span className="font-medium text-blue-800">İlerleme:</span>
İlerleme:
</span>
<span className="ml-1 text-blue-700"> <span className="ml-1 text-blue-700">
%{selectedProject.progress} %{selectedProject.progress}
</span> </span>
</div> </div>
<div> <div>
<span className="font-medium text-blue-800"> <span className="font-medium text-blue-800">Başlangıç:</span>
Başlangıç:
</span>
<span className="ml-1 text-blue-700"> <span className="ml-1 text-blue-700">
{selectedProject.startDate.toLocaleDateString( {selectedProject.startDate.toLocaleDateString('tr-TR')}
"tr-TR"
)}
</span> </span>
</div> </div>
<div> <div>
<span className="font-medium text-blue-800"> <span className="font-medium text-blue-800">Bitiş:</span>
Bitiş:
</span>
<span className="ml-1 text-blue-700"> <span className="ml-1 text-blue-700">
{selectedProject.endDate.toLocaleDateString( {selectedProject.endDate.toLocaleDateString('tr-TR')}
"tr-TR"
)}
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<div className="ml-1.5 text-right"> <div className="ml-1.5 text-right">
<div className="text-base font-bold text-blue-900"> <div className="text-base font-bold text-blue-900">
{selectedProject.budget.toLocaleString('tr-TR')}
{selectedProject.budget.toLocaleString(
"tr-TR"
)}
</div>
<div className="text-xs text-blue-700">
Bütçe
</div> </div>
<div className="text-xs text-blue-700">Bütçe</div>
</div> </div>
</div> </div>
</div> </div>
); )
})()} })()}
</div> </div>
@ -287,9 +258,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">ıklama</label>
ıklama
</label>
<textarea <textarea
name="description" name="description"
value={formData.description} value={formData.description}
@ -302,30 +271,18 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
Durum
</label>
<select <select
name="status" name="status"
value={formData.status} value={formData.status}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value={PhaseStatusEnum.NotStarted}> {Object.values(PhaseStatusEnum).map((status) => (
Başlanmadı <option key={status} value={status}>
</option> {getPhaseStatusText(status)}
<option value={PhaseStatusEnum.InProgress}> </option>
Devam Ediyor ))}
</option>
<option value={PhaseStatusEnum.Completed}>
Tamamlandı
</option>
<option value={PhaseStatusEnum.OnHold}>
Beklemede
</option>
<option value={PhaseStatusEnum.Cancelled}>
İptal Edildi
</option>
</select> </select>
</div> </div>
@ -340,11 +297,11 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value="">Kategori seçin...</option> <option value="">Kategori seçin...</option>
<option value="Planning">Planlama</option> {Object.values(PhaseCategoryEnum).map((cat) => (
<option value="Development">Geliştirme</option> <option key={cat} value={cat}>
<option value="Testing">Test</option> {getPhaseCategoryText(cat)}
<option value="Deployment">Dağıtım</option> </option>
<option value="Design">Tasarım</option> ))}
</select> </select>
</div> </div>
</div> </div>
@ -369,7 +326,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
<input <input
type="date" type="date"
name="startDate" name="startDate"
value={formData.startDate.toISOString().split("T")[0]} value={formData.startDate.toISOString().split('T')[0]}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
/> />
@ -382,7 +339,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
<input <input
type="date" type="date"
name="endDate" name="endDate"
value={formData.endDate.toISOString().split("T")[0]} value={formData.endDate.toISOString().split('T')[0]}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
/> />
@ -426,9 +383,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
<div className="flex items-center gap-2 text-blue-800"> <div className="flex items-center gap-2 text-blue-800">
<FaProjectDiagram className="w-4 h-4" /> <FaProjectDiagram className="w-4 h-4" />
<span className="text-sm font-medium">Aşama Kodu:</span> <span className="text-sm font-medium">Aşama Kodu:</span>
<span className="font-bold"> <span className="font-bold">{isEdit ? phase?.code : generatePhaseCode()}</span>
{isEdit ? phase?.code : generatePhaseCode()}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -449,13 +404,13 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2 shadow-md hover:shadow-lg" className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2 shadow-md hover:shadow-lg"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{isEdit ? "Güncelle" : "Oluştur"} {isEdit ? 'Güncelle' : 'Oluştur'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default PhaseEditModal; export default PhaseEditModal

View file

@ -66,6 +66,7 @@ import {
} from '../../../utils/erp' } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { mockCurrencies } from '@/mocks/mockCurrencies'
// Custom styles for the slider // Custom styles for the slider
const sliderStyles = ` const sliderStyles = `
@ -810,10 +811,11 @@ const ProjectForm: React.FC = () => {
}`} }`}
> >
<option value="">Tip seçin</option> <option value="">Tip seçin</option>
<option value="INTERNAL">İç Proje</option> {Object.values(ProjectTypeEnum).map((type) => (
<option value="CUSTOMER">Müşteri Projesi</option> <option key={type} value={type}>
<option value="RESEARCH">Ar-Ge Projesi</option> {getProjectTypeText(type)}
<option value="MAINTENANCE">Bakım Projesi</option> </option>
))}
</select> </select>
{errors.projectType && ( {errors.projectType && (
<p className="mt-1 text-sm text-red-600">{errors.projectType}</p> <p className="mt-1 text-sm text-red-600">{errors.projectType}</p>
@ -851,11 +853,11 @@ const ProjectForm: React.FC = () => {
onChange={(e) => handleInputChange('status', e.target.value)} onChange={(e) => handleInputChange('status', e.target.value)}
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="PLANNING">Planlama</option> {Object.values(ProjectStatusEnum).map((status) => (
<option value="ACTIVE">Aktif</option> <option key={status} value={status}>
<option value="ON_HOLD">Beklemede</option> {getProjectStatusText(status)}
<option value="COMPLETED">Tamamlandı</option> </option>
<option value="CANCELLED">İptal Edildi</option> ))}
</select> </select>
</div> </div>
@ -868,10 +870,11 @@ const ProjectForm: React.FC = () => {
onChange={(e) => handleInputChange('priority', e.target.value)} onChange={(e) => handleInputChange('priority', e.target.value)}
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="LOW">Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value="NORMAL">Normal</option> <option key={priority} value={priority}>
<option value="HIGH">Yüksek</option> {priority}
<option value="URGENT">Acil</option> </option>
))}
</select> </select>
</div> </div>
@ -884,9 +887,11 @@ const ProjectForm: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">Türk Lirası (TRY)</option> {mockCurrencies.map((currency) => (
<option value="USD">Amerikan Doları (USD)</option> <option key={currency.value} value={currency.value}>
<option value="EUR">Euro (EUR)</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -1238,9 +1243,11 @@ const ProjectForm: React.FC = () => {
onChange={(e) => handleInputChange('currency', e.target.value)} onChange={(e) => handleInputChange('currency', e.target.value)}
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
> >
<option value="TRY">Türk Lirası (TRY)</option> {mockCurrencies.map((currency) => (
<option value="USD">Amerikan Doları (USD)</option> <option key={currency.value} value={currency.value}>
<option value="EUR">Euro (EUR)</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>

View file

@ -12,8 +12,9 @@ import { mockProjects } from '../../../mocks/mockProjects'
import { mockProjectPhases } from '../../../mocks/mockProjectPhases' import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
import { mockProjectTasks } from '../../../mocks/mockProjectTasks' import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { getPriorityColor, getProjectStatusColor } from '../../../utils/erp' import { getFrequencyUnitText, getGanttStatusColor, getPriorityColor } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { FrequencyUnitEnum } from '@/types/pm'
interface ProjectGanttProps { interface ProjectGanttProps {
employeeId?: string employeeId?: string
@ -479,7 +480,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
if (task.type === 'task' && position.isVisible) { if (task.type === 'task' && position.isVisible) {
return ( return (
<div <div
className={`absolute h-4 sm:h-5 mt-0.5 rounded-sm ${getProjectStatusColor( className={`absolute h-4 sm:h-5 mt-0.5 rounded-sm ${getGanttStatusColor(
task.status, task.status,
)} shadow-md group cursor-pointer border border-white border-opacity-20`} )} shadow-md group cursor-pointer border border-white border-opacity-20`}
style={{ left: position.left, width: position.width }} style={{ left: position.left, width: position.width }}
@ -546,9 +547,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div> <div>
<h2 className="text-2xl font-bold text-gray-900">İş Yükü ve Proje Takibi</h2> <h2 className="text-2xl font-bold text-gray-900">İş Yükü ve Proje Takibi</h2>
<p className="text-gray-600"> <p className="text-gray-600">Tüm görevlerinizi merkezi bir noktadan yönetin.</p>
Tüm görevlerinizi merkezi bir noktadan yönetin.
</p>
</div> </div>
</div> </div>
@ -592,7 +591,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
<option value="">Tüm Çalışanlar</option> <option value="">Tüm Çalışanlar</option>
{mockEmployees.map((emp) => ( {mockEmployees.map((emp) => (
<option key={emp.id} value={emp.id}> <option key={emp.id} value={emp.id}>
{emp.firstName} {emp.lastName} {emp.fullName}
</option> </option>
))} ))}
</select> </select>
@ -602,10 +601,18 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')} onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')}
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto" className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto"
> >
<option value="day">Günlük</option> <option value={FrequencyUnitEnum.Days}>
<option value="week">Haftalık</option> {getFrequencyUnitText(FrequencyUnitEnum.Days)}
<option value="month">Aylık</option> </option>
<option value="year">Yıllık</option> <option value={FrequencyUnitEnum.Weeks}>
{getFrequencyUnitText(FrequencyUnitEnum.Weeks)}
</option>
<option value={FrequencyUnitEnum.Months}>
{getFrequencyUnitText(FrequencyUnitEnum.Months)}
</option>
<option value={FrequencyUnitEnum.Years}>
{getFrequencyUnitText(FrequencyUnitEnum.Years)}
</option>
</select> </select>
</div> </div>
</div> </div>

View file

@ -201,11 +201,11 @@ const ProjectList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={ProjectStatusEnum.Planning}>Planlama</option> {Object.values(ProjectStatusEnum).map((status) => (
<option value={ProjectStatusEnum.Active}>Aktif</option> <option key={status} value={status}>
<option value={ProjectStatusEnum.OnHold}>Beklemede</option> {getProjectStatusText(status)}
<option value={ProjectStatusEnum.Completed}>Tamamlandı</option> </option>
<option value={ProjectStatusEnum.Cancelled}>İptal Edildi</option> ))}
</select> </select>
</div> </div>
@ -217,10 +217,11 @@ const ProjectList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -12,7 +12,12 @@ import {
FaSave, FaSave,
FaProjectDiagram, FaProjectDiagram,
} from 'react-icons/fa' } from 'react-icons/fa'
import { PhaseStatusEnum, PsProjectPhase, ProjectStatusEnum } from '../../../types/ps' import {
PhaseStatusEnum,
PsProjectPhase,
ProjectStatusEnum,
PhaseCategoryEnum,
} from '../../../types/ps'
import { mockProjectPhases } from '../../../mocks/mockProjectPhases' import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
import { mockProjects } from '../../../mocks/mockProjects' import { mockProjects } from '../../../mocks/mockProjects'
import MultiSelectTeam from '../../../components/common/MultiSelectTeam' import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
@ -23,6 +28,8 @@ import {
getPhaseStatusIcon, getPhaseStatusIcon,
getPhaseStatusText, getPhaseStatusText,
getPhaseStatusColor, getPhaseStatusColor,
getProjectStatusText,
getPhaseCategoryText,
} from '../../../utils/erp' } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
@ -45,7 +52,7 @@ const ProjectPhases: React.FC = () => {
startDate: '', startDate: '',
endDate: '', endDate: '',
budget: 0, budget: 0,
category: '', category: PhaseCategoryEnum.Planning,
assignedTeams: [] as string[], assignedTeams: [] as string[],
}) })
@ -93,7 +100,7 @@ const ProjectPhases: React.FC = () => {
startDate: '', startDate: '',
endDate: '', endDate: '',
budget: 0, budget: 0,
category: '', category: PhaseCategoryEnum.Planning,
assignedTeams: [], assignedTeams: [],
}) })
setIsCreateModalOpen(true) setIsCreateModalOpen(true)
@ -247,11 +254,11 @@ const ProjectPhases: React.FC = () => {
className="px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500" className="px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500"
> >
<option value="All">Tüm Durumlar</option> <option value="All">Tüm Durumlar</option>
<option value={ProjectStatusEnum.Planning}>Başlanmadı</option> {Object.values(ProjectStatusEnum).map((status) => (
<option value={ProjectStatusEnum.Active}>Devam Ediyor</option> <option key={status} value={status}>
<option value={ProjectStatusEnum.OnHold}>Beklemede</option> {getProjectStatusText(status)}
<option value={ProjectStatusEnum.Completed}>Tamamlandı</option> </option>
<option value={ProjectStatusEnum.Cancelled}>İptal Edildi</option> ))}
</select> </select>
</div> </div>
@ -862,11 +869,11 @@ const ProjectPhases: React.FC = () => {
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value="">Kategori seçin...</option> <option value="">Kategori seçin...</option>
<option value="Planning">Planlama</option> {Object.values(PhaseCategoryEnum).map((cat) => (
<option value="Development">Geliştirme</option> <option key={cat} value={cat}>
<option value="Testing">Test</option> {getPhaseCategoryText(cat)}
<option value="Deployment">Dağıtım</option> </option>
<option value="Design">Tasarım</option> ))}
</select> </select>
</div> </div>
@ -880,11 +887,11 @@ const ProjectPhases: React.FC = () => {
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value={PhaseStatusEnum.NotStarted}>Başlanmadı</option> {Object.values(PhaseStatusEnum).map((status) => (
<option value={PhaseStatusEnum.InProgress}>Devam Ediyor</option> <option key={status} value={status}>
<option value={PhaseStatusEnum.Completed}>Tamamlandı</option> {getPhaseStatusText(status)}
<option value={PhaseStatusEnum.OnHold}>Beklemede</option> </option>
<option value={PhaseStatusEnum.Cancelled}>İptal Edildi</option> ))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -1,5 +1,5 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from "../../../types/ps"; import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from '../../../types/ps'
import { import {
FaSearch, FaSearch,
FaPlus, FaPlus,
@ -13,158 +13,157 @@ import {
FaFlag, FaFlag,
FaProjectDiagram, FaProjectDiagram,
FaUserCog, FaUserCog,
} from "react-icons/fa"; } from 'react-icons/fa'
import { mockProjectTasks } from "../../../mocks/mockProjectTasks"; import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
import { mockEmployees } from "../../../mocks/mockEmployees"; import { mockEmployees } from '../../../mocks/mockEmployees'
import { mockProjects } from "../../../mocks/mockProjects"; import { mockProjects } from '../../../mocks/mockProjects'
import { mockProjectPhases } from "../../../mocks/mockProjectPhases"; import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
import Widget from "../../../components/common/Widget"; import Widget from '../../../components/common/Widget'
import { PriorityEnum } from "../../../types/common"; import { PriorityEnum } from '../../../types/common'
import { import {
getTaskStatusColor, getTaskStatusColor,
getTaskStatusIcon, getTaskStatusIcon,
getPriorityColor, getPriorityColor,
getTaskTypeColor, getTaskTypeColor,
} from "../../../utils/erp"; getPriorityText,
import { Container } from "@/components/shared"; getTaskStatusText,
getTaskTypeText,
} from '../../../utils/erp'
import { Container } from '@/components/shared'
const ProjectTasks: React.FC = () => { const ProjectTasks: React.FC = () => {
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState('')
const [statusFilter, setStatusFilter] = useState<TaskStatusEnum | "">(""); const [statusFilter, setStatusFilter] = useState<TaskStatusEnum | ''>('')
const [selectedProjectFilter, setSelectedProjectFilter] = useState("All"); const [selectedProjectFilter, setSelectedProjectFilter] = useState('All')
const [selectedTask, setSelectedTask] = useState<PsProjectTask | null>(null); const [selectedTask, setSelectedTask] = useState<PsProjectTask | null>(null)
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false)
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false)
const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isEditModalOpen, setIsEditModalOpen] = useState(false)
const [editingTask, setEditingTask] = useState<PsProjectTask | null>(null); const [editingTask, setEditingTask] = useState<PsProjectTask | null>(null)
// Form state for creating/editing tasks // Form state for creating/editing tasks
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
name: "", name: '',
description: "", description: '',
projectId: "", projectId: '',
phaseId: "", phaseId: '',
taskType: TaskTypeEnum.Development, taskType: TaskTypeEnum.Development,
status: TaskStatusEnum.NotStarted, status: TaskStatusEnum.NotStarted,
priority: PriorityEnum.Normal, priority: PriorityEnum.Normal,
assignedTo: "", assignedTo: '',
assigneeEmail: "", assigneeEmail: '',
startDate: "", startDate: '',
endDate: "", endDate: '',
estimatedHours: 0, estimatedHours: 0,
progress: 0, progress: 0,
}); })
const filteredTasks = mockProjectTasks.filter((task) => { const filteredTasks = mockProjectTasks.filter((task) => {
const matchesSearch = const matchesSearch =
task.name.toLowerCase().includes(searchTerm.toLowerCase()) || task.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
task.taskCode.toLowerCase().includes(searchTerm.toLowerCase()) || task.taskCode.toLowerCase().includes(searchTerm.toLowerCase()) ||
(task.description && (task.description && task.description.toLowerCase().includes(searchTerm.toLowerCase()))
task.description.toLowerCase().includes(searchTerm.toLowerCase())); const matchesStatus = statusFilter === '' || task.status === statusFilter
const matchesStatus = statusFilter === "" || task.status === statusFilter;
const matchesProject = const matchesProject =
selectedProjectFilter === "All" || selectedProjectFilter === 'All' || task.projectId === selectedProjectFilter
task.projectId === selectedProjectFilter; return matchesSearch && matchesStatus && matchesProject
return matchesSearch && matchesStatus && matchesProject; })
});
const openModal = (task: PsProjectTask) => { const openModal = (task: PsProjectTask) => {
setSelectedTask(task); setSelectedTask(task)
setIsModalOpen(true); setIsModalOpen(true)
}; }
const closeModal = () => { const closeModal = () => {
setSelectedTask(null); setSelectedTask(null)
setIsModalOpen(false); setIsModalOpen(false)
}; }
const openCreateModal = () => { const openCreateModal = () => {
setFormData({ setFormData({
name: "", name: '',
description: "", description: '',
projectId: "", projectId: '',
phaseId: "", phaseId: '',
taskType: TaskTypeEnum.Development, taskType: TaskTypeEnum.Development,
status: TaskStatusEnum.NotStarted, status: TaskStatusEnum.NotStarted,
priority: PriorityEnum.Normal, priority: PriorityEnum.Normal,
assignedTo: "", assignedTo: '',
assigneeEmail: "", assigneeEmail: '',
startDate: "", startDate: '',
endDate: "", endDate: '',
estimatedHours: 0, estimatedHours: 0,
progress: 0, progress: 0,
}); })
setIsCreateModalOpen(true); setIsCreateModalOpen(true)
}; }
const closeCreateModal = () => { const closeCreateModal = () => {
setIsCreateModalOpen(false); setIsCreateModalOpen(false)
}; }
const openEditModal = (task: PsProjectTask) => { const openEditModal = (task: PsProjectTask) => {
setEditingTask(task); setEditingTask(task)
setFormData({ setFormData({
name: task.name, name: task.name,
description: task.description || "", description: task.description || '',
projectId: task.projectId || "", projectId: task.projectId || '',
phaseId: task.phaseId || "", phaseId: task.phaseId || '',
taskType: task.taskType, taskType: task.taskType,
status: task.status, status: task.status,
priority: task.priority, priority: task.priority,
assignedTo: task.assignedTo || "", assignedTo: task.assignedTo || '',
assigneeEmail: task.assignee?.email || "", assigneeEmail: task.assignee?.email || '',
startDate: task.startDate.toISOString().split("T")[0], startDate: task.startDate.toISOString().split('T')[0],
endDate: task.endDate.toISOString().split("T")[0], endDate: task.endDate.toISOString().split('T')[0],
estimatedHours: task.estimatedHours, estimatedHours: task.estimatedHours,
progress: task.progress, progress: task.progress,
}); })
setIsEditModalOpen(true); setIsEditModalOpen(true)
}; }
const closeEditModal = () => { const closeEditModal = () => {
setIsEditModalOpen(false); setIsEditModalOpen(false)
setEditingTask(null); setEditingTask(null)
}; }
const handleInputChange = ( const handleInputChange = (
e: React.ChangeEvent< e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
>
) => { ) => {
const { name, value } = e.target; const { name, value } = e.target
// Eğer atanan kişi seçimi yapılıyorsa, e-posta adresini otomatik doldur // Eğer atanan kişi seçimi yapılıyorsa, e-posta adresini otomatik doldur
if (name === "assignedTo") { if (name === 'assignedTo') {
const selectedEmployee = mockEmployees.find((emp) => emp.id === value); const selectedEmployee = mockEmployees.find((emp) => emp.id === value)
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: value, [name]: value,
assigneeEmail: selectedEmployee?.email || "", assigneeEmail: selectedEmployee?.email || '',
})); }))
} else { } else {
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: value, [name]: value,
})); }))
} }
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
// Here you would normally save to backend // Here you would normally save to backend
console.log("Saving task:", formData); console.log('Saving task:', formData)
alert(isEditModalOpen ? "Görev güncellendi!" : "Yeni görev oluşturuldu!"); alert(isEditModalOpen ? 'Görev güncellendi!' : 'Yeni görev oluşturuldu!')
if (isEditModalOpen) { if (isEditModalOpen) {
closeEditModal(); closeEditModal()
} else { } else {
closeCreateModal(); closeCreateModal()
} }
}; }
const generateTaskCode = () => { const generateTaskCode = () => {
const taskCount = mockProjectTasks.length + 1; const taskCount = mockProjectTasks.length + 1
return `TSK-${taskCount.toString().padStart(3, "0")}`; return `TSK-${taskCount.toString().padStart(3, '0')}`
}; }
return ( return (
<Container> <Container>
@ -172,9 +171,7 @@ const ProjectTasks: React.FC = () => {
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<div> <div>
<h2 className="text-2xl font-bold text-gray-900">Görev Yönetimi</h2> <h2 className="text-2xl font-bold text-gray-900">Görev Yönetimi</h2>
<p className="text-gray-600"> <p className="text-gray-600">Proje görevlerinizi oluşturun, düzenleyin ve takip edin</p>
Proje görevlerinizi oluşturun, düzenleyin ve takip edin
</p>
</div> </div>
<button <button
onClick={openCreateModal} onClick={openCreateModal}
@ -196,22 +193,14 @@ const ProjectTasks: React.FC = () => {
<Widget <Widget
title="Devam Eden" title="Devam Eden"
value={ value={mockProjectTasks.filter((t) => t.status === TaskStatusEnum.InProgress).length}
mockProjectTasks.filter(
(t) => t.status === TaskStatusEnum.InProgress
).length
}
color="yellow" color="yellow"
icon="FaClock" icon="FaClock"
/> />
<Widget <Widget
title="Tamamlanan" title="Tamamlanan"
value={ value={mockProjectTasks.filter((t) => t.status === TaskStatusEnum.Completed).length}
mockProjectTasks.filter(
(t) => t.status === TaskStatusEnum.Completed
).length
}
color="green" color="green"
icon="FaCheckCircle" icon="FaCheckCircle"
/> />
@ -222,9 +211,9 @@ const ProjectTasks: React.FC = () => {
mockProjectTasks.length > 0 mockProjectTasks.length > 0
? `${Math.round( ? `${Math.round(
mockProjectTasks.reduce((sum, t) => sum + t.progress, 0) / mockProjectTasks.reduce((sum, t) => sum + t.progress, 0) /
mockProjectTasks.length mockProjectTasks.length,
)}%` )}%`
: "0%" : '0%'
} }
color="red" color="red"
icon="FaBullseye" icon="FaBullseye"
@ -260,17 +249,15 @@ const ProjectTasks: React.FC = () => {
<select <select
value={statusFilter} value={statusFilter}
onChange={(e) => onChange={(e) => setStatusFilter(e.target.value as TaskStatusEnum | '')}
setStatusFilter(e.target.value as TaskStatusEnum | "")
}
className="w-full px-2.5 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full px-2.5 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="">Tüm Durumlar</option> <option value="">Tüm Durumlar</option>
<option value={TaskStatusEnum.NotStarted}>Başlanmadı</option> {Object.values(TaskStatusEnum).map((status) => (
<option value={TaskStatusEnum.InProgress}>Devam Ediyor</option> <option key={status} value={status}>
<option value={TaskStatusEnum.Completed}>Tamamlandı</option> {getTaskStatusText(status)}
<option value={TaskStatusEnum.OnHold}>Beklemede</option> </option>
<option value={TaskStatusEnum.Cancelled}>İptal Edildi</option> ))}
</select> </select>
</div> </div>
</div> </div>
@ -316,25 +303,21 @@ const ProjectTasks: React.FC = () => {
<tr <tr
key={task.id} key={task.id}
className={`hover:bg-blue-50 transition-colors duration-200 ${ className={`hover:bg-blue-50 transition-colors duration-200 ${
index % 2 === 0 ? "bg-white" : "bg-gray-50" index % 2 === 0 ? 'bg-white' : 'bg-gray-50'
}`} }`}
> >
<td className="px-2 py-1 whitespace-nowrap"> <td className="px-2 py-1 whitespace-nowrap">
<div> <div>
<div className="text-sm font-medium text-blue-700"> <div className="text-sm font-medium text-blue-700">
{(() => { {(() => {
const project = mockProjects.find( const project = mockProjects.find((p) => p.id === task.projectId)
(p) => p.id === task.projectId return project?.name || `Proje ID: ${task.projectId}`
);
return project?.name || `Proje ID: ${task.projectId}`;
})()} })()}
</div> </div>
<div className="text-xs text-gray-500"> <div className="text-xs text-gray-500">
{(() => { {(() => {
const project = mockProjects.find( const project = mockProjects.find((p) => p.id === task.projectId)
(p) => p.id === task.projectId return project?.code || task.projectId
);
return project?.code || task.projectId;
})()} })()}
</div> </div>
</div> </div>
@ -344,19 +327,15 @@ const ProjectTasks: React.FC = () => {
<div className="text-sm font-medium text-green-700"> <div className="text-sm font-medium text-green-700">
{task.phase?.name || {task.phase?.name ||
(() => { (() => {
const phase = mockProjectPhases.find( const phase = mockProjectPhases.find((p) => p.id === task.phaseId)
(p) => p.id === task.phaseId return phase?.name || `Aşama ID: ${task.phaseId}`
);
return phase?.name || `Aşama ID: ${task.phaseId}`;
})()} })()}
</div> </div>
<div className="text-xs text-gray-500"> <div className="text-xs text-gray-500">
{task.phase?.code || {task.phase?.code ||
(() => { (() => {
const phase = mockProjectPhases.find( const phase = mockProjectPhases.find((p) => p.id === task.phaseId)
(p) => p.id === task.phaseId return phase?.code || task.phaseId
);
return phase?.code || task.phaseId;
})()} })()}
</div> </div>
</div> </div>
@ -375,7 +354,7 @@ const ProjectTasks: React.FC = () => {
<td className="px-2 py-1 whitespace-nowrap"> <td className="px-2 py-1 whitespace-nowrap">
<span <span
className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-xs font-semibold ${getTaskStatusColor( className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-xs font-semibold ${getTaskStatusColor(
task.status task.status,
)}`} )}`}
> >
{getTaskStatusIcon(task.status)} {getTaskStatusIcon(task.status)}
@ -385,7 +364,7 @@ const ProjectTasks: React.FC = () => {
<td className="px-2 py-1 whitespace-nowrap"> <td className="px-2 py-1 whitespace-nowrap">
<span <span
className={`inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-semibold ${getPriorityColor( className={`inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-semibold ${getPriorityColor(
task.priority task.priority,
)}`} )}`}
> >
{task.priority} {task.priority}
@ -397,7 +376,7 @@ const ProjectTasks: React.FC = () => {
<FaUser className="w-4 h-4 text-blue-600" /> <FaUser className="w-4 h-4 text-blue-600" />
</div> </div>
<div className="text-sm text-gray-900 font-medium"> <div className="text-sm text-gray-900 font-medium">
{task.assignee?.fullName || "-"} {task.assignee?.fullName || '-'}
</div> </div>
</div> </div>
</td> </td>
@ -415,7 +394,7 @@ const ProjectTasks: React.FC = () => {
</div> </div>
</td> </td>
<td className="px-2 py-1 whitespace-nowrap text-sm text-gray-900 font-medium"> <td className="px-2 py-1 whitespace-nowrap text-sm text-gray-900 font-medium">
{task.endDate.toLocaleDateString("tr-TR")} {task.endDate.toLocaleDateString('tr-TR')}
</td> </td>
<td className="px-2 py-1 whitespace-nowrap text-sm font-medium"> <td className="px-2 py-1 whitespace-nowrap text-sm font-medium">
<div className="flex gap-1 justify-center"> <div className="flex gap-1 justify-center">
@ -446,12 +425,9 @@ const ProjectTasks: React.FC = () => {
<div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-2"> <div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-2">
<FaBullseye className="w-6 h-6 text-gray-400" /> <FaBullseye className="w-6 h-6 text-gray-400" />
</div> </div>
<h3 className="text-base font-medium text-gray-900 mb-1"> <h3 className="text-base font-medium text-gray-900 mb-1">Görev bulunamadı</h3>
Görev bulunamadı
</h3>
<p className="text-gray-500"> <p className="text-gray-500">
Arama kriterlerinizi değiştirmeyi deneyin veya yeni bir görev Arama kriterlerinizi değiştirmeyi deneyin veya yeni bir görev oluşturun.
oluşturun.
</p> </p>
</div> </div>
)} )}
@ -500,20 +476,17 @@ const ProjectTasks: React.FC = () => {
<div className="text-sm font-semibold text-blue-800"> <div className="text-sm font-semibold text-blue-800">
{(() => { {(() => {
const project = mockProjects.find( const project = mockProjects.find(
(p) => p.id === selectedTask.projectId (p) => p.id === selectedTask.projectId,
); )
return ( return project?.name || `Proje ID: ${selectedTask.projectId}`
project?.name ||
`Proje ID: ${selectedTask.projectId}`
);
})()} })()}
</div> </div>
<div className="text-xs text-blue-600 mt-1"> <div className="text-xs text-blue-600 mt-1">
{(() => { {(() => {
const project = mockProjects.find( const project = mockProjects.find(
(p) => p.id === selectedTask.projectId (p) => p.id === selectedTask.projectId,
); )
return project?.code || selectedTask.projectId; return project?.code || selectedTask.projectId
})()} })()}
</div> </div>
</div> </div>
@ -528,21 +501,18 @@ const ProjectTasks: React.FC = () => {
{selectedTask.phase?.name || {selectedTask.phase?.name ||
(() => { (() => {
const phase = mockProjectPhases.find( const phase = mockProjectPhases.find(
(p) => p.id === selectedTask.phaseId (p) => p.id === selectedTask.phaseId,
); )
return ( return phase?.name || `Aşama ID: ${selectedTask.phaseId}`
phase?.name ||
`Aşama ID: ${selectedTask.phaseId}`
);
})()} })()}
</div> </div>
<div className="text-xs text-green-600 mt-1"> <div className="text-xs text-green-600 mt-1">
{selectedTask.phase?.code || {selectedTask.phase?.code ||
(() => { (() => {
const phase = mockProjectPhases.find( const phase = mockProjectPhases.find(
(p) => p.id === selectedTask.phaseId (p) => p.id === selectedTask.phaseId,
); )
return phase?.code || selectedTask.phaseId; return phase?.code || selectedTask.phaseId
})()} })()}
</div> </div>
</div> </div>
@ -554,7 +524,7 @@ const ProjectTasks: React.FC = () => {
ıklama ıklama
</label> </label>
<p className="text-sm text-gray-900 bg-white p-2 rounded-lg border"> <p className="text-sm text-gray-900 bg-white p-2 rounded-lg border">
{selectedTask.description || "Açıklama bulunmuyor."} {selectedTask.description || 'Açıklama bulunmuyor.'}
</p> </p>
</div> </div>
@ -565,7 +535,7 @@ const ProjectTasks: React.FC = () => {
</label> </label>
<span <span
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getTaskTypeColor( className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getTaskTypeColor(
selectedTask.taskType selectedTask.taskType,
)}`} )}`}
> >
{selectedTask.taskType} {selectedTask.taskType}
@ -577,7 +547,7 @@ const ProjectTasks: React.FC = () => {
</label> </label>
<span <span
className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-lg text-xs font-semibold ${getTaskStatusColor( className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-lg text-xs font-semibold ${getTaskStatusColor(
selectedTask.status selectedTask.status,
)}`} )}`}
> >
{getTaskStatusIcon(selectedTask.status)} {getTaskStatusIcon(selectedTask.status)}
@ -592,7 +562,7 @@ const ProjectTasks: React.FC = () => {
</label> </label>
<span <span
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getPriorityColor( className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getPriorityColor(
selectedTask.priority selectedTask.priority,
)}`} )}`}
> >
{selectedTask.priority} {selectedTask.priority}
@ -612,9 +582,7 @@ const ProjectTasks: React.FC = () => {
<p className="text-sm font-medium text-gray-900"> <p className="text-sm font-medium text-gray-900">
{selectedTask.assignee.fullName} {selectedTask.assignee.fullName}
</p> </p>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">{selectedTask.assignee.email}</p>
{selectedTask.assignee.email}
</p>
</div> </div>
</div> </div>
) : ( ) : (
@ -641,7 +609,7 @@ const ProjectTasks: React.FC = () => {
Planlanan Başlangıç Planlanan Başlangıç
</label> </label>
<p className="text-sm text-gray-900 font-medium"> <p className="text-sm text-gray-900 font-medium">
{selectedTask.startDate.toLocaleDateString("tr-TR")} {selectedTask.startDate.toLocaleDateString('tr-TR')}
</p> </p>
</div> </div>
<div className="bg-white p-2 rounded-lg border"> <div className="bg-white p-2 rounded-lg border">
@ -649,9 +617,8 @@ const ProjectTasks: React.FC = () => {
Gerçek Başlangıç Gerçek Başlangıç
</label> </label>
<p className="text-sm text-gray-900 font-medium"> <p className="text-sm text-gray-900 font-medium">
{selectedTask.actualStartDate?.toLocaleDateString( {selectedTask.actualStartDate?.toLocaleDateString('tr-TR') ||
"tr-TR" 'Henüz başlanmadı'}
) || "Henüz başlanmadı"}
</p> </p>
</div> </div>
</div> </div>
@ -662,7 +629,7 @@ const ProjectTasks: React.FC = () => {
Planlanan Bitiş Planlanan Bitiş
</label> </label>
<p className="text-sm text-gray-900 font-medium"> <p className="text-sm text-gray-900 font-medium">
{selectedTask.endDate.toLocaleDateString("tr-TR")} {selectedTask.endDate.toLocaleDateString('tr-TR')}
</p> </p>
</div> </div>
<div className="bg-white p-2 rounded-lg border"> <div className="bg-white p-2 rounded-lg border">
@ -670,9 +637,8 @@ const ProjectTasks: React.FC = () => {
Gerçek Bitiş Gerçek Bitiş
</label> </label>
<p className="text-sm text-gray-900 font-medium"> <p className="text-sm text-gray-900 font-medium">
{selectedTask.actualEndDate?.toLocaleDateString( {selectedTask.actualEndDate?.toLocaleDateString('tr-TR') ||
"tr-TR" 'Henüz tamamlanmadı'}
) || "Henüz tamamlanmadı"}
</p> </p>
</div> </div>
</div> </div>
@ -727,9 +693,7 @@ const ProjectTasks: React.FC = () => {
Oluşturulma Oluşturulma
</label> </label>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
{selectedTask.creationTime.toLocaleDateString( {selectedTask.creationTime.toLocaleDateString('tr-TR')}
"tr-TR"
)}
</p> </p>
</div> </div>
<div> <div>
@ -737,9 +701,7 @@ const ProjectTasks: React.FC = () => {
Son Güncelleme Son Güncelleme
</label> </label>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
{selectedTask.lastModificationTime.toLocaleDateString( {selectedTask.lastModificationTime.toLocaleDateString('tr-TR')}
"tr-TR"
)}
</p> </p>
</div> </div>
</div> </div>
@ -759,8 +721,8 @@ const ProjectTasks: React.FC = () => {
</button> </button>
<button <button
onClick={() => { onClick={() => {
closeModal(); closeModal()
openEditModal(selectedTask!); openEditModal(selectedTask!)
}} }}
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-sm" className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-sm"
> >
@ -788,12 +750,12 @@ const ProjectTasks: React.FC = () => {
</div> </div>
<div> <div>
<h3 className="text-lg font-bold text-gray-900"> <h3 className="text-lg font-bold text-gray-900">
{isEditModalOpen ? "Görev Düzenle" : "Yeni Görev Oluştur"} {isEditModalOpen ? 'Görev Düzenle' : 'Yeni Görev Oluştur'}
</h3> </h3>
<p className="text-xs text-gray-600"> <p className="text-xs text-gray-600">
{isEditModalOpen {isEditModalOpen
? "Mevcut görev bilgilerini güncelleyin" ? 'Mevcut görev bilgilerini güncelleyin'
: "Yeni bir görev tanımlayın"} : 'Yeni bir görev tanımlayın'}
</p> </p>
</div> </div>
</div> </div>
@ -850,16 +812,11 @@ const ProjectTasks: React.FC = () => {
disabled={!formData.projectId} disabled={!formData.projectId}
> >
<option value=""> <option value="">
{formData.projectId {formData.projectId ? 'Aşama seçin...' : 'Önce proje seçin'}
? "Aşama seçin..."
: "Önce proje seçin"}
</option> </option>
{formData.projectId && {formData.projectId &&
mockProjectPhases mockProjectPhases
.filter( .filter((phase) => phase.projectId === formData.projectId)
(phase) =>
phase.projectId === formData.projectId
)
.map((phase) => ( .map((phase) => (
<option key={phase.id} value={phase.id}> <option key={phase.id} value={phase.id}>
{phase.code} - {phase.name} {phase.code} - {phase.name}
@ -907,18 +864,11 @@ const ProjectTasks: React.FC = () => {
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value={TaskTypeEnum.Development}> {Object.values(TaskTypeEnum).map((type) => (
Geliştirme <option key={type} value={type}>
</option> {getTaskTypeText(type)}
<option value={TaskTypeEnum.Testing}>Test</option> </option>
<option value={TaskTypeEnum.Documentation}> ))}
Dokümantasyon
</option>
<option value={TaskTypeEnum.Review}>İnceleme</option>
<option value={TaskTypeEnum.Deployment}>
Dağıtım
</option>
<option value={TaskTypeEnum.Meeting}>Toplantı</option>
</select> </select>
</div> </div>
@ -932,10 +882,11 @@ const ProjectTasks: React.FC = () => {
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
@ -949,21 +900,11 @@ const ProjectTasks: React.FC = () => {
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
> >
<option value={TaskStatusEnum.NotStarted}> {Object.values(TaskStatusEnum).map((status) => (
Başlanmadı <option key={status} value={status}>
</option> {getTaskStatusText(status)}
<option value={TaskStatusEnum.InProgress}> </option>
Devam Ediyor ))}
</option>
<option value={TaskStatusEnum.Completed}>
Tamamlandı
</option>
<option value={TaskStatusEnum.OnHold}>
Beklemede
</option>
<option value={TaskStatusEnum.Cancelled}>
İptal Edildi
</option>
</select> </select>
</div> </div>
</div> </div>
@ -994,8 +935,7 @@ const ProjectTasks: React.FC = () => {
.filter((emp) => emp.isActive) .filter((emp) => emp.isActive)
.map((employee) => ( .map((employee) => (
<option key={employee.id} value={employee.id}> <option key={employee.id} value={employee.id}>
{employee.fullName} -{" "} {employee.fullName} - {employee.jobPosition?.name}
{employee.jobPosition?.name}
</option> </option>
))} ))}
</select> </select>
@ -1021,8 +961,8 @@ const ProjectTasks: React.FC = () => {
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200"> <div className="bg-blue-50 p-2 rounded-lg border border-blue-200">
{(() => { {(() => {
const selectedEmployee = mockEmployees.find( const selectedEmployee = mockEmployees.find(
(emp) => emp.id === formData.assignedTo (emp) => emp.id === formData.assignedTo,
); )
return selectedEmployee ? ( return selectedEmployee ? (
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center"> <div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center">
@ -1040,7 +980,7 @@ const ProjectTasks: React.FC = () => {
</p> </p>
</div> </div>
</div> </div>
) : null; ) : null
})()} })()}
</div> </div>
)} )}
@ -1126,9 +1066,7 @@ const ProjectTasks: React.FC = () => {
<FaFlag className="w-4 h-4" /> <FaFlag className="w-4 h-4" />
<span className="text-sm font-medium">Görev Kodu:</span> <span className="text-sm font-medium">Görev Kodu:</span>
<span className="font-bold"> <span className="font-bold">
{isEditModalOpen {isEditModalOpen ? editingTask?.taskCode : generateTaskCode()}
? editingTask?.taskCode
: generateTaskCode()}
</span> </span>
</div> </div>
</div> </div>
@ -1150,7 +1088,7 @@ const ProjectTasks: React.FC = () => {
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md" className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{isEditModalOpen ? "Güncelle" : "Oluştur"} {isEditModalOpen ? 'Güncelle' : 'Oluştur'}
</button> </button>
</div> </div>
</form> </form>
@ -1158,8 +1096,7 @@ const ProjectTasks: React.FC = () => {
</div> </div>
)} )}
</Container> </Container>
)
}
); export default ProjectTasks
};
export default ProjectTasks;

View file

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react'
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from "../../../types/ps"; import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from '../../../types/ps'
import { import {
FaPlus, FaPlus,
FaEdit, FaEdit,
@ -10,39 +10,40 @@ import {
FaUserCog, FaUserCog,
FaSave, FaSave,
FaTimesCircle, FaTimesCircle,
} from "react-icons/fa"; } from 'react-icons/fa'
import { mockEmployees } from "../../../mocks/mockEmployees"; import { mockEmployees } from '../../../mocks/mockEmployees'
import { mockProjects } from "../../../mocks/mockProjects"; import { mockProjects } from '../../../mocks/mockProjects'
import { mockProjectPhases } from "../../../mocks/mockProjectPhases"; import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
import { PriorityEnum } from "../../../types/common"; import { PriorityEnum } from '../../../types/common'
import { getPriorityText, getTaskStatusText, getTaskTypeText } from '@/utils/erp'
export interface TaskFormData { export interface TaskFormData {
name: string; name: string
description: string; description: string
projectId: string; projectId: string
phaseId: string; phaseId: string
taskType: TaskTypeEnum; taskType: TaskTypeEnum
status: TaskStatusEnum; status: TaskStatusEnum
priority: PriorityEnum; priority: PriorityEnum
assignedTo: string; assignedTo: string
assigneeEmail: string; assigneeEmail: string
startDate: string; startDate: string
endDate: string; endDate: string
estimatedHours: number; estimatedHours: number
progress: number; progress: number
} }
interface TaskEditModalProps { interface TaskEditModalProps {
isOpen: boolean; isOpen: boolean
onClose: () => void; onClose: () => void
task?: PsProjectTask | null; task?: PsProjectTask | null
onSubmit: (taskData: TaskFormData) => void; onSubmit: (taskData: TaskFormData) => void
mode: "create" | "edit"; mode: 'create' | 'edit'
defaultProjectId?: string; defaultProjectId?: string
} }
const inputClasses = const inputClasses =
"w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"; 'w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors'
const TaskEditModal: React.FC<TaskEditModalProps> = ({ const TaskEditModal: React.FC<TaskEditModalProps> = ({
isOpen, isOpen,
@ -53,91 +54,89 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
defaultProjectId, defaultProjectId,
}) => { }) => {
const [formData, setFormData] = useState<TaskFormData>({ const [formData, setFormData] = useState<TaskFormData>({
name: "", name: '',
description: "", description: '',
projectId: "", projectId: '',
phaseId: "", phaseId: '',
taskType: TaskTypeEnum.Development, taskType: TaskTypeEnum.Development,
status: TaskStatusEnum.NotStarted, status: TaskStatusEnum.NotStarted,
priority: PriorityEnum.Normal, priority: PriorityEnum.Normal,
assignedTo: "", assignedTo: '',
assigneeEmail: "", assigneeEmail: '',
startDate: "", startDate: '',
endDate: "", endDate: '',
estimatedHours: 0, estimatedHours: 0,
progress: 0, progress: 0,
}); })
const generateTaskCode = () => { const generateTaskCode = () => {
const taskCount = 1; // Bu gerçek uygulamada dinamik olarak hesaplanmalı const taskCount = 1 // Bu gerçek uygulamada dinamik olarak hesaplanmalı
return `TSK-${taskCount.toString().padStart(3, "0")}`; return `TSK-${taskCount.toString().padStart(3, '0')}`
}; }
useEffect(() => { useEffect(() => {
if (mode === "edit" && task) { if (mode === 'edit' && task) {
setFormData({ setFormData({
name: task.name, name: task.name,
description: task.description || "", description: task.description || '',
projectId: task.projectId, projectId: task.projectId,
phaseId: task.phaseId || "", phaseId: task.phaseId || '',
taskType: task.taskType, taskType: task.taskType,
status: task.status, status: task.status,
priority: task.priority, priority: task.priority,
assignedTo: task.assignedTo || "", assignedTo: task.assignedTo || '',
assigneeEmail: task.assignee?.email || "", assigneeEmail: task.assignee?.email || '',
startDate: task.startDate.toISOString().split("T")[0], startDate: task.startDate.toISOString().split('T')[0],
endDate: task.endDate.toISOString().split("T")[0], endDate: task.endDate.toISOString().split('T')[0],
estimatedHours: task.estimatedHours, estimatedHours: task.estimatedHours,
progress: task.progress, progress: task.progress,
}); })
} else { } else {
// Reset form for create mode // Reset form for create mode
setFormData({ setFormData({
name: "", name: '',
description: "", description: '',
projectId: defaultProjectId || "", projectId: defaultProjectId || '',
phaseId: "", phaseId: '',
taskType: TaskTypeEnum.Development, taskType: TaskTypeEnum.Development,
status: TaskStatusEnum.NotStarted, status: TaskStatusEnum.NotStarted,
priority: PriorityEnum.Normal, priority: PriorityEnum.Normal,
assignedTo: "", assignedTo: '',
assigneeEmail: "", assigneeEmail: '',
startDate: "", startDate: '',
endDate: "", endDate: '',
estimatedHours: 0, estimatedHours: 0,
progress: 0, progress: 0,
}); })
} }
}, [mode, task, isOpen, defaultProjectId]); }, [mode, task, isOpen, defaultProjectId])
const handleInputChange = ( const handleInputChange = (
e: React.ChangeEvent< e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
>
) => { ) => {
const { name, value } = e.target; const { name, value } = e.target
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: value, [name]: value,
})); }))
// Auto-fill email when employee is selected // Auto-fill email when employee is selected
if (name === "assignedTo") { if (name === 'assignedTo') {
const selectedEmployee = mockEmployees.find((emp) => emp.id === value); const selectedEmployee = mockEmployees.find((emp) => emp.id === value)
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
assigneeEmail: selectedEmployee?.email || "", assigneeEmail: selectedEmployee?.email || '',
})); }))
} }
}; }
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
onSubmit(formData); onSubmit(formData)
onClose(); onClose()
}; }
if (!isOpen) return null; if (!isOpen) return null
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
@ -146,7 +145,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
<div className="flex items-center justify-between p-2.5 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-t-xl"> <div className="flex items-center justify-between p-2.5 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-t-xl">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="w-6 h-6 bg-blue-600 rounded-md flex items-center justify-center"> <div className="w-6 h-6 bg-blue-600 rounded-md flex items-center justify-center">
{mode === "edit" ? ( {mode === 'edit' ? (
<FaEdit className="w-3.5 h-3.5 text-white" /> <FaEdit className="w-3.5 h-3.5 text-white" />
) : ( ) : (
<FaPlus className="w-3.5 h-3.5 text-white" /> <FaPlus className="w-3.5 h-3.5 text-white" />
@ -154,12 +153,12 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
</div> </div>
<div> <div>
<h3 className="text-lg font-bold text-gray-900"> <h3 className="text-lg font-bold text-gray-900">
{mode === "edit" ? "Görev Düzenle" : "Yeni Görev Oluştur"} {mode === 'edit' ? 'Görev Düzenle' : 'Yeni Görev Oluştur'}
</h3> </h3>
<p className="text-xs text-gray-600"> <p className="text-xs text-gray-600">
{mode === "edit" {mode === 'edit'
? "Mevcut görev bilgilerini güncelleyin" ? 'Mevcut görev bilgilerini güncelleyin'
: "Yeni bir görev tanımlayın"} : 'Yeni bir görev tanımlayın'}
</p> </p>
</div> </div>
</div> </div>
@ -217,15 +216,11 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
disabled={!formData.projectId} disabled={!formData.projectId}
> >
<option value=""> <option value="">
{formData.projectId {formData.projectId ? 'Aşama seçin...' : 'Önce proje seçin'}
? "Aşama seçin..."
: "Önce proje seçin"}
</option> </option>
{formData.projectId && {formData.projectId &&
mockProjectPhases mockProjectPhases
.filter( .filter((phase) => phase.projectId === formData.projectId)
(phase) => phase.projectId === formData.projectId
)
.map((phase) => ( .map((phase) => (
<option key={phase.id} value={phase.id}> <option key={phase.id} value={phase.id}>
{phase.code} - {phase.name} {phase.code} - {phase.name}
@ -250,9 +245,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">ıklama</label>
ıklama
</label>
<textarea <textarea
name="description" name="description"
value={formData.description} value={formData.description}
@ -273,59 +266,43 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
onChange={handleInputChange} onChange={handleInputChange}
className={inputClasses} className={inputClasses}
> >
<option value={TaskTypeEnum.Development}> {Object.values(TaskTypeEnum).map((type) => (
Geliştirme <option key={type} value={type}>
</option> {getTaskTypeText(type)}
<option value={TaskTypeEnum.Testing}>Test</option> </option>
<option value={TaskTypeEnum.Documentation}> ))}
Dokümantasyon
</option>
<option value={TaskTypeEnum.Review}>İnceleme</option>
<option value={TaskTypeEnum.Deployment}>Dağıtım</option>
<option value={TaskTypeEnum.Meeting}>Toplantı</option>
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Öncelik</label>
Öncelik
</label>
<select <select
name="priority" name="priority"
value={formData.priority} value={formData.priority}
onChange={handleInputChange} onChange={handleInputChange}
className={inputClasses} className={inputClasses}
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
Durum
</label>
<select <select
name="status" name="status"
value={formData.status} value={formData.status}
onChange={handleInputChange} onChange={handleInputChange}
className={inputClasses} className={inputClasses}
> >
<option value={TaskStatusEnum.NotStarted}> {Object.values(TaskStatusEnum).map((status) => (
Başlanmadı <option key={status} value={status}>
</option> {getTaskStatusText(status)}
<option value={TaskStatusEnum.InProgress}> </option>
Devam Ediyor ))}
</option>
<option value={TaskStatusEnum.Completed}>
Tamamlandı
</option>
<option value={TaskStatusEnum.OnHold}>Beklemede</option>
<option value={TaskStatusEnum.Cancelled}>
İptal Edildi
</option>
</select> </select>
</div> </div>
</div> </div>
@ -363,9 +340,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
E-posta
</label>
<input <input
type="email" type="email"
name="assigneeEmail" name="assigneeEmail"
@ -381,8 +356,8 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
{formData.assignedTo && {formData.assignedTo &&
(() => { (() => {
const selectedEmployee = mockEmployees.find( const selectedEmployee = mockEmployees.find(
(emp) => emp.id === formData.assignedTo (emp) => emp.id === formData.assignedTo,
); )
return selectedEmployee ? ( return selectedEmployee ? (
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200 flex items-center gap-2"> <div className="bg-blue-50 p-2 rounded-lg border border-blue-200 flex items-center gap-2">
<div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center shrink-0"> <div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center shrink-0">
@ -400,7 +375,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
</p> </p>
</div> </div>
</div> </div>
) : null; ) : null
})()} })()}
<div className="grid grid-cols-2 gap-2.5"> <div className="grid grid-cols-2 gap-2.5">
@ -448,7 +423,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
/> />
</div> </div>
{mode === "edit" && ( {mode === 'edit' && (
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
İlerleme (%) İlerleme (%)
@ -484,7 +459,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
<FaFlag className="w-4 h-4" /> <FaFlag className="w-4 h-4" />
<span className="text-sm font-medium">Görev Kodu:</span> <span className="text-sm font-medium">Görev Kodu:</span>
<span className="font-bold"> <span className="font-bold">
{mode === "edit" ? task?.taskCode : generateTaskCode()} {mode === 'edit' ? task?.taskCode : generateTaskCode()}
</span> </span>
</div> </div>
</div> </div>
@ -506,13 +481,13 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md hover:shadow-lg" className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md hover:shadow-lg"
> >
<FaSave className="w-4 h-4" /> <FaSave className="w-4 h-4" />
{mode === "edit" ? "Güncelle" : "Oluştur"} {mode === 'edit' ? 'Güncelle' : 'Oluştur'}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
); )
}; }
export default TaskEditModal; export default TaskEditModal

View file

@ -8,6 +8,7 @@ import {
} from '../../../types/mm' } from '../../../types/mm'
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee' import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
import { mockDepartments } from '../../../mocks/mockDepartments' import { mockDepartments } from '../../../mocks/mockDepartments'
import { getApprovalLevelText, getRequestTypeText } from '@/utils/erp'
interface ApprovalWorkflowModalProps { interface ApprovalWorkflowModalProps {
isOpen: boolean isOpen: boolean
@ -195,10 +196,11 @@ const ApprovalWorkflowModal: React.FC<ApprovalWorkflowModalProps> = ({
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={RequestTypeEnum.Material}>Malzeme</option> {Object.values(RequestTypeEnum).map((type) => (
<option value={RequestTypeEnum.Service}>Hizmet</option> <option key={type} value={type}>
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option> {getRequestTypeText(type)}
<option value={RequestTypeEnum.Maintenance}>Bakım</option> </option>
))}
</select> </select>
</div> </div>
@ -276,14 +278,11 @@ const ApprovalWorkflowModal: React.FC<ApprovalWorkflowModalProps> = ({
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={ApprovalLevelEnum.Supervisor}>Süpervizör</option> {Object.values(ApprovalLevelEnum).map((lvl) => (
<option value={ApprovalLevelEnum.Manager}>Müdür</option> <option key={lvl} value={lvl}>
<option value={ApprovalLevelEnum.Director}>Direktör</option> {getApprovalLevelText(lvl)}
<option value={ApprovalLevelEnum.GeneralManager}>Genel Müdür</option> </option>
<option value={ApprovalLevelEnum.FinanceManager}> ))}
Mali İşler Müdürü
</option>
<option value={ApprovalLevelEnum.TechnicalManager}>Teknik Müdür</option>
</select> </select>
</div> </div>

View file

@ -210,15 +210,11 @@ const DeliveryTracking: React.FC = () => {
className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={DeliveryStatusEnum.Preparing}>Hazırlanıyor</option> {Object.values(DeliveryStatusEnum).map((status) => (
<option value={DeliveryStatusEnum.Shipped}>Kargoya Verildi</option> <option key={status} value={status}>
<option value={DeliveryStatusEnum.InTransit}>Yolda</option> {getDeliveryStatusText(status)}
<option value={DeliveryStatusEnum.OutForDelivery}>Dağıtımda</option> </option>
<option value={DeliveryStatusEnum.Delivered}>Teslim Edildi</option> ))}
<option value={DeliveryStatusEnum.PartiallyDelivered}>Kısmi Teslim</option>
<option value={DeliveryStatusEnum.Delayed}>Gecikmeli</option>
<option value={DeliveryStatusEnum.Returned}>İade Edildi</option>
<option value={DeliveryStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>
</div> </div>

View file

@ -6,6 +6,9 @@ import {
QualityStatusEnum, QualityStatusEnum,
MmGoodsReceiptItem, MmGoodsReceiptItem,
} from '../../../types/mm' } from '../../../types/mm'
import { mock } from 'node:test'
import { mockWarehouses } from '@/mocks/mockWarehouses'
import { getQualityStatusText, getReceiptStatusText } from '@/utils/erp'
interface DeliveryTrackingModalProps { interface DeliveryTrackingModalProps {
isOpen: boolean isOpen: boolean
@ -226,10 +229,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
required required
> >
<option value="">Depo Seçiniz</option> <option value="">Depo Seçiniz</option>
<option value="WH001">Ana Depo</option> {mockWarehouses.map((wh) => (
<option value="WH002">Hammadde Deposu</option> <option key={wh.id} value={wh.id}>
<option value="WH003">Mamul Deposu</option> {wh.name}
<option value="WH004">Yedek Parça Deposu</option> </option>
))}
</select> </select>
</div> </div>
@ -242,10 +246,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={ReceiptStatusEnum.Pending}>Beklemede</option> {Object.values(ReceiptStatusEnum).map((status) => (
<option value={ReceiptStatusEnum.InProgress}>İşlemde</option> <option key={status} value={status}>
<option value={ReceiptStatusEnum.Completed}>Tamamlandı</option> {getReceiptStatusText(status)}
<option value={ReceiptStatusEnum.OnHold}>Bekletildi</option> </option>
))}
</select> </select>
</div> </div>
@ -402,10 +407,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={QualityStatusEnum.Pending}>Beklemede</option> {Object.values(QualityStatusEnum).map((status) => (
<option value={QualityStatusEnum.Approved}>Kabul</option> <option key={status} value={status}>
<option value={QualityStatusEnum.Rejected}>Red</option> {getQualityStatusText(status)}
<option value={QualityStatusEnum.Conditional}>Koşullu</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -1,4 +1,5 @@
import { MaterialTypeEnum, MmMaterialType } from '@/types/mm' import { MaterialTypeEnum, MmMaterialType } from '@/types/mm'
import { getMaterialTypeText } from '@/utils/erp'
import { useState } from 'react' import { useState } from 'react'
interface MaterialTypeModalProps { interface MaterialTypeModalProps {
@ -43,12 +44,11 @@ const MaterialTypeModal: React.FC<MaterialTypeModalProps> = ({ type, onSave, onC
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required required
> >
<option value={MaterialTypeEnum.RawMaterial}>Hammadde</option> {Object.values(MaterialTypeEnum).map((value) => (
<option value={MaterialTypeEnum.SemiFinished}>Yarı Mamul</option> <option key={value} value={value}>
<option value={MaterialTypeEnum.Finished}>Mamul</option> {getMaterialTypeText(value)}
<option value={MaterialTypeEnum.Consumable}>Sarf Malzemesi</option> </option>
<option value={MaterialTypeEnum.Service}>Hizmet</option> ))}
<option value={MaterialTypeEnum.Spare}>Yedek Parça</option>
</select> </select>
</div> </div>

View file

@ -2,7 +2,7 @@ import React, { useState } from 'react'
import { FaPlus, FaEdit, FaTrash, FaSearch, FaTh, FaList } from 'react-icons/fa' import { FaPlus, FaEdit, FaTrash, FaSearch, FaTh, FaList } from 'react-icons/fa'
import { MmMaterialType, MaterialTypeEnum } from '../../../types/mm' import { MmMaterialType, MaterialTypeEnum } from '../../../types/mm'
import { mockMaterialTypes } from '../../../mocks/mockMaterialTypes' import { mockMaterialTypes } from '../../../mocks/mockMaterialTypes'
import { getMaterialTypeDisplay } from '../../../utils/erp' import { getMaterialTypeText } from '../../../utils/erp'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import MaterialTypeModal from './MaterialTypeModal' import MaterialTypeModal from './MaterialTypeModal'
@ -151,7 +151,7 @@ const MaterialTypes: React.FC = () => {
<tr key={type.id} className="hover:bg-gray-50 text-xs"> <tr key={type.id} className="hover:bg-gray-50 text-xs">
<td className="px-3 py-1.5 whitespace-nowrap"> <td className="px-3 py-1.5 whitespace-nowrap">
<span className="text-sm font-mono font-medium text-gray-900"> <span className="text-sm font-mono font-medium text-gray-900">
{getMaterialTypeDisplay(type.code)} {getMaterialTypeText(type.code)}
</span> </span>
</td> </td>
<td className="px-3 py-1.5 whitespace-nowrap"> <td className="px-3 py-1.5 whitespace-nowrap">
@ -206,7 +206,7 @@ const MaterialTypes: React.FC = () => {
<div className="flex items-start justify-between mb-3"> <div className="flex items-start justify-between mb-3">
<div className="flex-1"> <div className="flex-1">
<span className="text-xs font-mono font-medium text-blue-600 bg-blue-50 px-2 py-1 rounded"> <span className="text-xs font-mono font-medium text-blue-600 bg-blue-50 px-2 py-1 rounded">
{getMaterialTypeDisplay(type.code)} {getMaterialTypeText(type.code)}
</span> </span>
</div> </div>
<div className="flex items-center space-x-1"> <div className="flex items-center space-x-1">

View file

@ -195,15 +195,11 @@ const OrderManagement: React.FC = () => {
className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="all">Tüm Durumlar</option> <option value="all">Tüm Durumlar</option>
<option value={OrderStatusEnum.Draft}>Taslak</option> {Object.values(OrderStatusEnum).map((status) => (
<option value={OrderStatusEnum.Pending}>Beklemede</option> <option key={status} value={status}>
<option value={OrderStatusEnum.Approved}>Onaylandı</option> {getOrderStatusText(status)}
<option value={OrderStatusEnum.Sent}>Gönderildi</option> </option>
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option> ))}
<option value={OrderStatusEnum.PartiallyDelivered}>Kısmi Teslim</option>
<option value={OrderStatusEnum.Delivered}>Teslim Edildi</option>
<option value={OrderStatusEnum.Completed}>Tamamlandı</option>
<option value={OrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>
</div> </div>
@ -559,14 +555,11 @@ const OrderManagement: React.FC = () => {
defaultValue="" defaultValue=""
> >
<option value="">Durum Seçiniz</option> <option value="">Durum Seçiniz</option>
<option value={OrderStatusEnum.Pending}>Beklemede</option> {Object.values(OrderStatusEnum).map((status) => (
<option value={OrderStatusEnum.Approved}>Onaylandı</option> <option key={status} value={status}>
<option value={OrderStatusEnum.Sent}>Gönderildi</option> {getOrderStatusText(status)}
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option> </option>
<option value={OrderStatusEnum.PartiallyDelivered}>Kısmi Teslim</option> ))}
<option value={OrderStatusEnum.Delivered}>Teslim Edildi</option>
<option value={OrderStatusEnum.Completed}>Tamamlandı</option>
<option value={OrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>

View file

@ -19,6 +19,8 @@ import { mockPurchaseOrders } from '../../../mocks/mockPurchaseOrders'
import { Address, PaymentTerms } from '../../../types/common' import { Address, PaymentTerms } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { getOrderStatusText, getPaymentTermsText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
const OrderManagementForm: React.FC = () => { const OrderManagementForm: React.FC = () => {
const { id } = useParams<{ id: string }>() const { id } = useParams<{ id: string }>()
@ -318,14 +320,11 @@ const OrderManagementForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={PaymentTerms.Net15}>15 Gün Vadeli</option> {Object.values(PaymentTerms).map((term) => (
<option value={PaymentTerms.Net30}>30 Gün Vadeli</option> <option key={term} value={term}>
<option value={PaymentTerms.Net45}>45 Gün Vadeli</option> {getPaymentTermsText(term)}
<option value={PaymentTerms.Net60}>60 Gün Vadeli</option> </option>
<option value={PaymentTerms.Net90}>90 Gün Vadeli</option> ))}
<option value={PaymentTerms.COD}>Kapıda Ödeme</option>
<option value={PaymentTerms.Prepaid}>Peşin</option>
<option value={PaymentTerms.Cash}>Nakit</option>
</select> </select>
</div> </div>
@ -338,9 +337,11 @@ const OrderManagementForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
@ -654,14 +655,11 @@ const OrderManagementForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={OrderStatusEnum.Draft}>Taslak</option> {Object.values(OrderStatusEnum).map((status) => (
<option value={OrderStatusEnum.Sent}>Gönderildi</option> <option key={status} value={status}>
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option> {getOrderStatusText(status)}
<option value={OrderStatusEnum.PartiallyReceived}>Kısmi Teslim</option> </option>
<option value={OrderStatusEnum.Received}>Teslim Alındı</option> ))}
<option value={OrderStatusEnum.Invoiced}>Faturalandı</option>
<option value={OrderStatusEnum.Closed}>Kapatıldı</option>
<option value={OrderStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>

View file

@ -21,6 +21,8 @@ import { mockPurchaseRequests } from '../../../mocks/mockPurchaseRequests'
import { PriorityEnum } from '../../../types/common' import { PriorityEnum } from '../../../types/common'
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { getPriorityText, getRequestStatusText, getRequestTypeText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
const PurchaseRequestForm: React.FC = () => { const PurchaseRequestForm: React.FC = () => {
const { id } = useParams<{ id: string }>() const { id } = useParams<{ id: string }>()
@ -198,10 +200,11 @@ const PurchaseRequestForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={RequestTypeEnum.Material}>Malzeme</option> {Object.values(RequestTypeEnum).map((type) => (
<option value={RequestTypeEnum.Service}>Hizmet</option> <option key={type} value={type}>
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option> {getRequestTypeText(type)}
<option value={RequestTypeEnum.Maintenance}>Bakım</option> </option>
))}
</select> </select>
</div> </div>
@ -294,10 +297,11 @@ const PurchaseRequestForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>
@ -310,9 +314,11 @@ const PurchaseRequestForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value="TRY">TRY</option> {mockCurrencies.map((currency) => (
<option value="USD">USD</option> <option key={currency.value} value={currency.value}>
<option value="EUR">EUR</option> {currency.value} - {currency.label}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
@ -500,12 +506,11 @@ const PurchaseRequestForm: React.FC = () => {
disabled={isReadOnly} disabled={isReadOnly}
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500" className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
> >
<option value={RequestStatusEnum.Draft}>Taslak</option> {Object.values(RequestStatusEnum).map((status) => (
<option value={RequestStatusEnum.Submitted}>Gönderildi</option> <option key={status} value={status}>
<option value={RequestStatusEnum.InReview}>İncelemede</option> {getRequestStatusText(status)}
<option value={RequestStatusEnum.Approved}>Onaylandı</option> </option>
<option value={RequestStatusEnum.Rejected}>Reddedildi</option> ))}
<option value={RequestStatusEnum.Cancelled}>İptal Edildi</option>
</select> </select>
</div> </div>

View file

@ -96,23 +96,24 @@ const PurchaseRequests: React.FC = () => {
onChange={(e) => setFilterStatus(e.target.value as RequestStatusEnum | 'ALL')} onChange={(e) => setFilterStatus(e.target.value as RequestStatusEnum | 'ALL')}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="ALL">Tüm Durumlar</option> <option value="All">Tüm Durumlar</option>
<option value={RequestStatusEnum.Draft}>Taslak</option> {Object.values(RequestStatusEnum).map((status) => (
<option value={RequestStatusEnum.Submitted}>Gönderildi</option> <option key={status} value={status}>
<option value={RequestStatusEnum.InReview}>İnceleniyor</option> {getRequestStatusText(status)}
<option value={RequestStatusEnum.Approved}>Onaylandı</option> </option>
<option value={RequestStatusEnum.Rejected}>Reddedildi</option> ))}
</select> </select>
<select <select
value={filterType} value={filterType}
onChange={(e) => setFilterType(e.target.value as RequestTypeEnum | 'ALL')} onChange={(e) => setFilterType(e.target.value as RequestTypeEnum | 'ALL')}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
> >
<option value="ALL">Tüm Türler</option> <option value="All">Tüm Türler</option>
<option value={RequestTypeEnum.Material}>Malzeme</option> {Object.values(RequestTypeEnum).map((type) => (
<option value={RequestTypeEnum.Service}>Hizmet</option> <option key={type} value={type}>
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option> {getRequestTypeText(type)}
<option value={RequestTypeEnum.Maintenance}>Bakım</option> </option>
))}
</select> </select>
</div> </div>

View file

@ -141,11 +141,11 @@ const PurchaseRequisitionList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={RequisitionStatusEnum.Draft}>Taslak</option> {Object.values(RequisitionStatusEnum).map((status) => (
<option value={RequisitionStatusEnum.Submitted}>Gönderildi</option> <option key={status} value={status}>
<option value={RequisitionStatusEnum.InApproval}>Onayda</option> {getRequisitionStatusText(status)}
<option value={RequisitionStatusEnum.Approved}>Onaylandı</option> </option>
<option value={RequisitionStatusEnum.Rejected}>Reddedildi</option> ))}
</select> </select>
</div> </div>
@ -157,10 +157,11 @@ const PurchaseRequisitionList: React.FC = () => {
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
> >
<option value="all">Tümü</option> <option value="all">Tümü</option>
<option value={PriorityEnum.Low}>Düşük</option> {Object.values(PriorityEnum).map((priority) => (
<option value={PriorityEnum.Normal}>Normal</option> <option key={priority} value={priority}>
<option value={PriorityEnum.High}>Yüksek</option> {getPriorityText(priority)}
<option value={PriorityEnum.Urgent}>Acil</option> </option>
))}
</select> </select>
</div> </div>

Some files were not shown because too many files have changed in this diff Show more