Enum ve static veriler düzenlendi.
This commit is contained in:
parent
a86d0f9fd1
commit
ca28fe8b5c
116 changed files with 4170 additions and 4649 deletions
|
|
@ -82,7 +82,7 @@ define(['./workbox-a959eb95'], (function (workbox) { 'use strict';
|
|||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "/index.html",
|
||||
"revision": "0.bkv2hic80pg"
|
||||
"revision": "0.h99odp2o5hg"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), {
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ const EntityManager: React.FC = () => {
|
|||
</p>
|
||||
{!searchTerm && filterActive === 'all' && (
|
||||
<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"
|
||||
>
|
||||
<FaPlus className="w-4 h-4" />
|
||||
|
|
|
|||
|
|
@ -1,54 +1,51 @@
|
|||
import { BankAccountTypeEnum } from "../types/fi";
|
||||
import { BusinessParty, BusinessPartyStatusEnum, PartyType, PaymentTerms } from "../types/common";
|
||||
import {
|
||||
CustomerSegmentEnum,
|
||||
CustomerTypeEnum,
|
||||
} from "../types/crm";
|
||||
import { SupplierTypeEnum, SupplierCardTypeEnum } from "../types/mm";
|
||||
import { BankAccountTypeEnum } from '../types/fi'
|
||||
import { BusinessParty, BusinessPartyStatusEnum, PartyType, PaymentTerms } from '../types/common'
|
||||
import { CustomerSegmentEnum, CustomerTypeEnum } from '../types/crm'
|
||||
import { SupplierTypeEnum, SupplierCardTypeEnum } from '../types/mm'
|
||||
|
||||
export const mockBusinessParties: BusinessParty[] = [
|
||||
{
|
||||
id: "1",
|
||||
code: "SUP001",
|
||||
supplierType: SupplierTypeEnum.Material,
|
||||
name: "ABC Malzeme Ltd.",
|
||||
id: '1',
|
||||
code: 'SUP001',
|
||||
supplierType: SupplierTypeEnum.Manufacturer,
|
||||
name: 'ABC Malzeme Ltd.',
|
||||
primaryContact: {
|
||||
id: "2",
|
||||
firstName: "Fatma",
|
||||
lastName: "Demir",
|
||||
fullName: "Fatma Demir",
|
||||
title: "Genel Müdür",
|
||||
department: "Yönetim",
|
||||
email: "fatma.demir@uretim.com",
|
||||
phone: "+90 312 555 0202",
|
||||
mobile: "+90 532 555 0202",
|
||||
id: '2',
|
||||
firstName: 'Fatma',
|
||||
lastName: 'Demir',
|
||||
fullName: 'Fatma Demir',
|
||||
title: 'Genel Müdür',
|
||||
department: 'Yönetim',
|
||||
email: 'fatma.demir@uretim.com',
|
||||
phone: '+90 312 555 0202',
|
||||
mobile: '+90 532 555 0202',
|
||||
isPrimary: true,
|
||||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
},
|
||||
email: "aliveli@gmail.com",
|
||||
phone: "+90 212 555 1234",
|
||||
email: 'aliveli@gmail.com',
|
||||
phone: '+90 212 555 1234',
|
||||
address: {
|
||||
street: "İstiklal Cad. No:10",
|
||||
city: "İstanbul",
|
||||
state: "İstanbul",
|
||||
postalCode: "34430",
|
||||
country: "Türkiye",
|
||||
street: 'İstiklal Cad. No:10',
|
||||
city: 'İstanbul',
|
||||
state: 'İstanbul',
|
||||
postalCode: '34430',
|
||||
country: 'Türkiye',
|
||||
},
|
||||
taxNumber: "1234567890",
|
||||
taxNumber: '1234567890',
|
||||
paymentTerms: PaymentTerms.Net30,
|
||||
currency: "TRY",
|
||||
cardNumber: "SC-2024-001",
|
||||
currency: 'TRY',
|
||||
cardNumber: 'SC-2024-001',
|
||||
cardType: SupplierCardTypeEnum.Standard,
|
||||
validFrom: new Date("2024-01-01"),
|
||||
validTo: new Date("2024-12-31"),
|
||||
validFrom: new Date('2024-01-01'),
|
||||
validTo: new Date('2024-12-31'),
|
||||
creditLimit: 500000,
|
||||
isActive: true,
|
||||
currentBalance: 120000,
|
||||
discountRate: 5,
|
||||
specialConditions: ["Toplu sipariş indirimi", "Öncelikli teslimat"],
|
||||
lastOrderDate: new Date("2024-08-15"),
|
||||
specialConditions: ['Toplu sipariş indirimi', 'Öncelikli teslimat'],
|
||||
lastOrderDate: new Date('2024-08-15'),
|
||||
performanceMetrics: {
|
||||
deliveryPerformance: 95,
|
||||
qualityRating: 90,
|
||||
|
|
@ -56,21 +53,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
responsiveness: 67,
|
||||
complianceRating: 88,
|
||||
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: [
|
||||
{
|
||||
id: "BA001",
|
||||
bankName: "Garanti BBVA",
|
||||
accountNumber: "1234567890",
|
||||
iban: "TR330006100519786457841326",
|
||||
swiftCode: "TGBATRIS",
|
||||
id: 'BA001',
|
||||
bankName: 'Garanti BBVA',
|
||||
accountNumber: '1234567890',
|
||||
iban: 'TR330006100519786457841326',
|
||||
swiftCode: 'TGBATRIS',
|
||||
isDefault: true,
|
||||
accountCode: "",
|
||||
branchName: "",
|
||||
accountCode: '',
|
||||
branchName: '',
|
||||
accountType: BankAccountTypeEnum.Current,
|
||||
currency: "",
|
||||
currency: '',
|
||||
balance: 0,
|
||||
overdraftLimit: 0,
|
||||
dailyTransferLimit: 0,
|
||||
|
|
@ -81,14 +78,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
],
|
||||
contacts: [
|
||||
{
|
||||
id: "C001",
|
||||
firstName: "Ali",
|
||||
lastName: "Veli",
|
||||
fullName: "Ali Veli",
|
||||
title: "Satınalma Müdürü",
|
||||
email: "aliveli@gmail.com",
|
||||
phone: "+90 212 555 1234",
|
||||
department: "Satınalma",
|
||||
id: 'C001',
|
||||
firstName: 'Ali',
|
||||
lastName: 'Veli',
|
||||
fullName: 'Ali Veli',
|
||||
title: 'Satınalma Müdürü',
|
||||
email: 'aliveli@gmail.com',
|
||||
phone: '+90 212 555 1234',
|
||||
department: 'Satınalma',
|
||||
isPrimary: true,
|
||||
isActive: false,
|
||||
creationTime: new Date(),
|
||||
|
|
@ -100,47 +97,47 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
partyType: PartyType.Supplier,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
code: "SUP002",
|
||||
supplierType: SupplierTypeEnum.Service,
|
||||
name: "XYZ Teknoloji A.Ş.",
|
||||
id: '2',
|
||||
code: 'SUP002',
|
||||
supplierType: SupplierTypeEnum.ServiceProvider,
|
||||
name: 'XYZ Teknoloji A.Ş.',
|
||||
primaryContact: {
|
||||
id: "2",
|
||||
firstName: "Fatma",
|
||||
lastName: "Demir",
|
||||
fullName: "Fatma Demir",
|
||||
title: "Genel Müdür",
|
||||
department: "Yönetim",
|
||||
email: "fatma.demir@uretim.com",
|
||||
phone: "+90 312 555 0202",
|
||||
mobile: "+90 532 555 0202",
|
||||
id: '2',
|
||||
firstName: 'Fatma',
|
||||
lastName: 'Demir',
|
||||
fullName: 'Fatma Demir',
|
||||
title: 'Genel Müdür',
|
||||
department: 'Yönetim',
|
||||
email: 'fatma.demir@uretim.com',
|
||||
phone: '+90 312 555 0202',
|
||||
mobile: '+90 532 555 0202',
|
||||
isPrimary: true,
|
||||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
},
|
||||
email: "aysedemir@gmail.com",
|
||||
phone: "+90 216 555 5678",
|
||||
email: 'aysedemir@gmail.com',
|
||||
phone: '+90 216 555 5678',
|
||||
address: {
|
||||
street: "Barbaros Bulv. No:20",
|
||||
city: "İstanbul",
|
||||
state: "İstanbul",
|
||||
postalCode: "34746",
|
||||
country: "Türkiye",
|
||||
street: 'Barbaros Bulv. No:20',
|
||||
city: 'İstanbul',
|
||||
state: 'İstanbul',
|
||||
postalCode: '34746',
|
||||
country: 'Türkiye',
|
||||
},
|
||||
taxNumber: "0987654321",
|
||||
taxNumber: '0987654321',
|
||||
paymentTerms: PaymentTerms.Net15,
|
||||
currency: "TRY",
|
||||
cardNumber: "SC-2024-002",
|
||||
currency: 'TRY',
|
||||
cardNumber: 'SC-2024-002',
|
||||
cardType: SupplierCardTypeEnum.Premium,
|
||||
validFrom: new Date("2024-02-01"),
|
||||
validTo: new Date("2024-12-31"),
|
||||
validFrom: new Date('2024-02-01'),
|
||||
validTo: new Date('2024-12-31'),
|
||||
creditLimit: 250000,
|
||||
isActive: true,
|
||||
currentBalance: 75000,
|
||||
discountRate: 3,
|
||||
specialConditions: ["Hızlı teslimat", "Kalite garantisi"],
|
||||
lastOrderDate: new Date("2024-08-20"),
|
||||
specialConditions: ['Hızlı teslimat', 'Kalite garantisi'],
|
||||
lastOrderDate: new Date('2024-08-20'),
|
||||
performanceMetrics: {
|
||||
deliveryPerformance: 88,
|
||||
qualityRating: 90,
|
||||
|
|
@ -148,21 +145,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
responsiveness: 87,
|
||||
complianceRating: 91,
|
||||
overallScore: 88,
|
||||
lastEvaluationDate: new Date("2024-08-01"),
|
||||
lastEvaluationDate: new Date('2024-08-01'),
|
||||
},
|
||||
certifications: ["ISO 9001"],
|
||||
certifications: ['ISO 9001'],
|
||||
bankAccounts: [
|
||||
{
|
||||
id: "BA002",
|
||||
bankName: "İş Bankası",
|
||||
accountNumber: "0987654321",
|
||||
iban: "TR440006200519786457841327",
|
||||
swiftCode: "ISBKTRIS",
|
||||
id: 'BA002',
|
||||
bankName: 'İş Bankası',
|
||||
accountNumber: '0987654321',
|
||||
iban: 'TR440006200519786457841327',
|
||||
swiftCode: 'ISBKTRIS',
|
||||
isDefault: true,
|
||||
accountCode: "",
|
||||
branchName: "",
|
||||
accountCode: '',
|
||||
branchName: '',
|
||||
accountType: BankAccountTypeEnum.Current,
|
||||
currency: "",
|
||||
currency: '',
|
||||
balance: 0,
|
||||
overdraftLimit: 0,
|
||||
dailyTransferLimit: 0,
|
||||
|
|
@ -173,14 +170,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
],
|
||||
contacts: [
|
||||
{
|
||||
id: "C002",
|
||||
firstName: "Ayşe",
|
||||
lastName: "Demir",
|
||||
fullName: "Ayşe Demir",
|
||||
title: "Satış Müdürü",
|
||||
email: "aysedemir@gmail.com",
|
||||
phone: "+90 216 555 5678",
|
||||
department: "Satış",
|
||||
id: 'C002',
|
||||
firstName: 'Ayşe',
|
||||
lastName: 'Demir',
|
||||
fullName: 'Ayşe Demir',
|
||||
title: 'Satış Müdürü',
|
||||
email: 'aysedemir@gmail.com',
|
||||
phone: '+90 216 555 5678',
|
||||
department: 'Satış',
|
||||
isPrimary: true,
|
||||
isActive: false,
|
||||
creationTime: new Date(),
|
||||
|
|
@ -192,47 +189,47 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
partyType: PartyType.Supplier,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
code: "SUP003",
|
||||
supplierType: SupplierTypeEnum.Both,
|
||||
name: "LMN Endüstri A.Ş.",
|
||||
id: '3',
|
||||
code: 'SUP003',
|
||||
supplierType: SupplierTypeEnum.Manufacturer,
|
||||
name: 'LMN Endüstri A.Ş.',
|
||||
primaryContact: {
|
||||
id: "2",
|
||||
firstName: "Fatma",
|
||||
lastName: "Demir",
|
||||
fullName: "Fatma Demir",
|
||||
title: "Genel Müdür",
|
||||
department: "Yönetim",
|
||||
email: "fatma.demir@uretim.com",
|
||||
phone: "+90 312 555 0202",
|
||||
mobile: "+90 532 555 0202",
|
||||
id: '2',
|
||||
firstName: 'Fatma',
|
||||
lastName: 'Demir',
|
||||
fullName: 'Fatma Demir',
|
||||
title: 'Genel Müdür',
|
||||
department: 'Yönetim',
|
||||
email: 'fatma.demir@uretim.com',
|
||||
phone: '+90 312 555 0202',
|
||||
mobile: '+90 532 555 0202',
|
||||
isPrimary: true,
|
||||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
},
|
||||
email: "mehmetyilmaz@gmail.com",
|
||||
phone: "+90 232 555 7890",
|
||||
email: 'mehmetyilmaz@gmail.com',
|
||||
phone: '+90 232 555 7890',
|
||||
address: {
|
||||
street: "Atatürk Cad. No:5",
|
||||
city: "İzmir",
|
||||
state: "İzmir",
|
||||
postalCode: "35210",
|
||||
country: "Türkiye",
|
||||
street: 'Atatürk Cad. No:5',
|
||||
city: 'İzmir',
|
||||
state: 'İzmir',
|
||||
postalCode: '35210',
|
||||
country: 'Türkiye',
|
||||
},
|
||||
taxNumber: "1122334455",
|
||||
taxNumber: '1122334455',
|
||||
paymentTerms: PaymentTerms.Net45,
|
||||
currency: "TRY",
|
||||
cardNumber: "SC-2024-003",
|
||||
currency: 'TRY',
|
||||
cardNumber: 'SC-2024-003',
|
||||
cardType: SupplierCardTypeEnum.Preferred,
|
||||
validFrom: new Date("2024-03-01"),
|
||||
validTo: new Date("2024-12-31"),
|
||||
validFrom: new Date('2024-03-01'),
|
||||
validTo: new Date('2024-12-31'),
|
||||
creditLimit: 150000,
|
||||
isActive: true,
|
||||
currentBalance: 45000,
|
||||
discountRate: 2,
|
||||
specialConditions: ["Toplu sipariş indirimi"],
|
||||
lastOrderDate: new Date("2024-08-18"),
|
||||
specialConditions: ['Toplu sipariş indirimi'],
|
||||
lastOrderDate: new Date('2024-08-18'),
|
||||
performanceMetrics: {
|
||||
deliveryPerformance: 82,
|
||||
qualityRating: 85,
|
||||
|
|
@ -240,21 +237,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
responsiveness: 80,
|
||||
complianceRating: 88,
|
||||
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: [
|
||||
{
|
||||
id: "BA003",
|
||||
bankName: "Yapı Kredi",
|
||||
accountNumber: "1122334455",
|
||||
iban: "TR550006300519786457841328",
|
||||
swiftCode: "YAPITRIS",
|
||||
id: 'BA003',
|
||||
bankName: 'Yapı Kredi',
|
||||
accountNumber: '1122334455',
|
||||
iban: 'TR550006300519786457841328',
|
||||
swiftCode: 'YAPITRIS',
|
||||
isDefault: true,
|
||||
accountCode: "",
|
||||
branchName: "",
|
||||
accountCode: '',
|
||||
branchName: '',
|
||||
accountType: BankAccountTypeEnum.Current,
|
||||
currency: "",
|
||||
currency: '',
|
||||
balance: 0,
|
||||
overdraftLimit: 0,
|
||||
dailyTransferLimit: 0,
|
||||
|
|
@ -265,14 +262,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
],
|
||||
contacts: [
|
||||
{
|
||||
id: "C003",
|
||||
firstName: "Mehmet",
|
||||
lastName: "Yılmaz",
|
||||
fullName: "Mehmet Yılmaz",
|
||||
title: "Genel Müdür",
|
||||
email: "mehmetyilmaz@gmail.com",
|
||||
phone: "+90 232 555 7890",
|
||||
department: "Yönetim",
|
||||
id: 'C003',
|
||||
firstName: 'Mehmet',
|
||||
lastName: 'Yılmaz',
|
||||
fullName: 'Mehmet Yılmaz',
|
||||
title: 'Genel Müdür',
|
||||
email: 'mehmetyilmaz@gmail.com',
|
||||
phone: '+90 232 555 7890',
|
||||
department: 'Yönetim',
|
||||
isPrimary: true,
|
||||
isActive: false,
|
||||
creationTime: new Date(),
|
||||
|
|
@ -284,47 +281,47 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
partyType: PartyType.Supplier,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
code: "SUP004",
|
||||
supplierType: SupplierTypeEnum.Material,
|
||||
name: "OPQ Ticaret Ltd.",
|
||||
id: '4',
|
||||
code: 'SUP004',
|
||||
supplierType: SupplierTypeEnum.Distributor,
|
||||
name: 'OPQ Ticaret Ltd.',
|
||||
primaryContact: {
|
||||
id: "2",
|
||||
firstName: "Fatma",
|
||||
lastName: "Demir",
|
||||
fullName: "Fatma Demir",
|
||||
title: "Genel Müdür",
|
||||
department: "Yönetim",
|
||||
email: "fatma.demir@uretim.com",
|
||||
phone: "+90 312 555 0202",
|
||||
mobile: "+90 532 555 0202",
|
||||
id: '2',
|
||||
firstName: 'Fatma',
|
||||
lastName: 'Demir',
|
||||
fullName: 'Fatma Demir',
|
||||
title: 'Genel Müdür',
|
||||
department: 'Yönetim',
|
||||
email: 'fatma.demir@uretim.com',
|
||||
phone: '+90 312 555 0202',
|
||||
mobile: '+90 532 555 0202',
|
||||
isPrimary: true,
|
||||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
},
|
||||
email: "fatmacelik@gmail.com",
|
||||
phone: "+90 312 555 3456",
|
||||
email: 'fatmacelik@gmail.com',
|
||||
phone: '+90 312 555 3456',
|
||||
address: {
|
||||
street: "Kızılay Meydanı No:15",
|
||||
city: "Ankara",
|
||||
state: "Ankara",
|
||||
postalCode: "06690",
|
||||
country: "Türkiye",
|
||||
street: 'Kızılay Meydanı No:15',
|
||||
city: 'Ankara',
|
||||
state: 'Ankara',
|
||||
postalCode: '06690',
|
||||
country: 'Türkiye',
|
||||
},
|
||||
taxNumber: "6677889900",
|
||||
taxNumber: '6677889900',
|
||||
paymentTerms: PaymentTerms.Net30,
|
||||
currency: "TRY",
|
||||
cardNumber: "SC-2024-004",
|
||||
currency: 'TRY',
|
||||
cardNumber: 'SC-2024-004',
|
||||
cardType: SupplierCardTypeEnum.Standard,
|
||||
validFrom: new Date("2024-04-01"),
|
||||
validTo: new Date("2024-12-31"),
|
||||
validFrom: new Date('2024-04-01'),
|
||||
validTo: new Date('2024-12-31'),
|
||||
creditLimit: 100000,
|
||||
isActive: false,
|
||||
currentBalance: 30000,
|
||||
discountRate: 4,
|
||||
specialConditions: ["Öncelikli sipariş", "Hızlı teslimat"],
|
||||
lastOrderDate: new Date("2024-06-30"),
|
||||
specialConditions: ['Öncelikli sipariş', 'Hızlı teslimat'],
|
||||
lastOrderDate: new Date('2024-06-30'),
|
||||
performanceMetrics: {
|
||||
deliveryPerformance: 75,
|
||||
qualityRating: 78,
|
||||
|
|
@ -332,21 +329,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
responsiveness: 76,
|
||||
complianceRating: 80,
|
||||
overallScore: 78,
|
||||
lastEvaluationDate: new Date("2024-07-01"),
|
||||
lastEvaluationDate: new Date('2024-07-01'),
|
||||
},
|
||||
certifications: ["ISO 9001"],
|
||||
certifications: ['ISO 9001'],
|
||||
bankAccounts: [
|
||||
{
|
||||
id: "BA004",
|
||||
bankName: "Halkbank",
|
||||
accountNumber: "6677889900",
|
||||
iban: "TR660006400519786457841329",
|
||||
swiftCode: "HALKTRIS",
|
||||
id: 'BA004',
|
||||
bankName: 'Halkbank',
|
||||
accountNumber: '6677889900',
|
||||
iban: 'TR660006400519786457841329',
|
||||
swiftCode: 'HALKTRIS',
|
||||
isDefault: true,
|
||||
accountCode: "",
|
||||
branchName: "",
|
||||
accountCode: '',
|
||||
branchName: '',
|
||||
accountType: BankAccountTypeEnum.Current,
|
||||
currency: "",
|
||||
currency: '',
|
||||
balance: 0,
|
||||
overdraftLimit: 0,
|
||||
dailyTransferLimit: 0,
|
||||
|
|
@ -357,14 +354,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
],
|
||||
contacts: [
|
||||
{
|
||||
id: "C004",
|
||||
firstName: "Fatma",
|
||||
lastName: "Çelik",
|
||||
fullName: "Fatma Çelik",
|
||||
title: "Finans Müdürü",
|
||||
email: "fatmacelik@gmail.com",
|
||||
phone: "+90 312 555 3456",
|
||||
department: "Finans",
|
||||
id: 'C004',
|
||||
firstName: 'Fatma',
|
||||
lastName: 'Çelik',
|
||||
fullName: 'Fatma Çelik',
|
||||
title: 'Finans Müdürü',
|
||||
email: 'fatmacelik@gmail.com',
|
||||
phone: '+90 312 555 3456',
|
||||
department: 'Finans',
|
||||
isPrimary: true,
|
||||
isActive: false,
|
||||
creationTime: new Date(),
|
||||
|
|
@ -376,22 +373,22 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
partyType: PartyType.Supplier,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
code: "CUST-002",
|
||||
name: "Üretim Ltd.",
|
||||
id: '5',
|
||||
code: 'CUST-002',
|
||||
name: 'Üretim Ltd.',
|
||||
customerType: CustomerTypeEnum.Company,
|
||||
industry: "İmalat",
|
||||
website: "www.uretim.com",
|
||||
industry: 'İmalat',
|
||||
website: 'www.uretim.com',
|
||||
primaryContact: {
|
||||
id: "2",
|
||||
firstName: "Fatma",
|
||||
lastName: "Demir",
|
||||
fullName: "Fatma Demir",
|
||||
title: "Genel Müdür",
|
||||
department: "Yönetim",
|
||||
email: "fatma.demir@uretim.com",
|
||||
phone: "+90 312 555 0202",
|
||||
mobile: "+90 532 555 0202",
|
||||
id: '2',
|
||||
firstName: 'Fatma',
|
||||
lastName: 'Demir',
|
||||
fullName: 'Fatma Demir',
|
||||
title: 'Genel Müdür',
|
||||
department: 'Yönetim',
|
||||
email: 'fatma.demir@uretim.com',
|
||||
phone: '+90 312 555 0202',
|
||||
mobile: '+90 532 555 0202',
|
||||
isPrimary: true,
|
||||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
|
|
@ -399,50 +396,50 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
},
|
||||
contacts: [],
|
||||
address: {
|
||||
street: "Sanayi Sitesi 5. Cadde No:25",
|
||||
city: "Ankara",
|
||||
state: "Ankara",
|
||||
postalCode: "06000",
|
||||
country: "Türkiye",
|
||||
street: 'Sanayi Sitesi 5. Cadde No:25',
|
||||
city: 'Ankara',
|
||||
state: 'Ankara',
|
||||
postalCode: '06000',
|
||||
country: 'Türkiye',
|
||||
},
|
||||
taxNumber: "0987654321",
|
||||
registrationNumber: "REG-002",
|
||||
taxNumber: '0987654321',
|
||||
registrationNumber: 'REG-002',
|
||||
creditLimit: 500000,
|
||||
paymentTerms: PaymentTerms.Net60,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: BusinessPartyStatusEnum.Active,
|
||||
customerSegment: CustomerSegmentEnum.SMB,
|
||||
assignedSalesRep: "REP-002",
|
||||
teamId: "TEAM-001",
|
||||
assignedSalesRep: 'REP-002',
|
||||
teamId: 'TEAM-001',
|
||||
totalRevenue: 850000,
|
||||
lastOrderDate: new Date("2024-01-10"),
|
||||
lastOrderDate: new Date('2024-01-10'),
|
||||
averageOrderValue: 42500,
|
||||
lifetimeValue: 1700000,
|
||||
opportunities: [],
|
||||
orders: [],
|
||||
activities: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-09-20"),
|
||||
lastModificationTime: new Date("2024-01-18"),
|
||||
creationTime: new Date('2023-09-20'),
|
||||
lastModificationTime: new Date('2024-01-18'),
|
||||
partyType: PartyType.Customer,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
code: "CUST-001",
|
||||
name: "Teknoloji A.Ş.",
|
||||
id: '6',
|
||||
code: 'CUST-001',
|
||||
name: 'Teknoloji A.Ş.',
|
||||
customerType: CustomerTypeEnum.Company,
|
||||
industry: "Teknoloji",
|
||||
website: "www.teknoloji.com",
|
||||
industry: 'Teknoloji',
|
||||
website: 'www.teknoloji.com',
|
||||
primaryContact: {
|
||||
id: "1",
|
||||
firstName: "Ali",
|
||||
lastName: "Yılmaz",
|
||||
fullName: "Ali Yılmaz",
|
||||
title: "Satınalma Müdürü",
|
||||
department: "Satınalma",
|
||||
email: "ali.yilmaz@teknoloji.com",
|
||||
phone: "+90 212 555 0201",
|
||||
mobile: "+90 532 555 0201",
|
||||
id: '1',
|
||||
firstName: 'Ali',
|
||||
lastName: 'Yılmaz',
|
||||
fullName: 'Ali Yılmaz',
|
||||
title: 'Satınalma Müdürü',
|
||||
department: 'Satınalma',
|
||||
email: 'ali.yilmaz@teknoloji.com',
|
||||
phone: '+90 212 555 0201',
|
||||
mobile: '+90 532 555 0201',
|
||||
isPrimary: true,
|
||||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
|
|
@ -450,53 +447,53 @@ export const mockBusinessParties: BusinessParty[] = [
|
|||
},
|
||||
contacts: [],
|
||||
address: {
|
||||
street: "Teknoloji Caddesi No:100",
|
||||
city: "İstanbul",
|
||||
state: "İstanbul",
|
||||
postalCode: "34000",
|
||||
country: "Türkiye",
|
||||
street: 'Teknoloji Caddesi No:100',
|
||||
city: 'İstanbul',
|
||||
state: 'İstanbul',
|
||||
postalCode: '34000',
|
||||
country: 'Türkiye',
|
||||
},
|
||||
taxNumber: "1234567890",
|
||||
registrationNumber: "REG-001",
|
||||
taxNumber: '1234567890',
|
||||
registrationNumber: 'REG-001',
|
||||
creditLimit: 1000000,
|
||||
paymentTerms: PaymentTerms.Net30,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: BusinessPartyStatusEnum.Active,
|
||||
customerSegment: CustomerSegmentEnum.Enterprise,
|
||||
assignedSalesRep: "REP-001",
|
||||
teamId: "TEAM-001",
|
||||
assignedSalesRep: 'REP-001',
|
||||
teamId: 'TEAM-001',
|
||||
totalRevenue: 2500000,
|
||||
lastOrderDate: new Date("2024-01-15"),
|
||||
lastOrderDate: new Date('2024-01-15'),
|
||||
averageOrderValue: 125000,
|
||||
lifetimeValue: 5000000,
|
||||
opportunities: [],
|
||||
orders: [],
|
||||
activities: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-06-15"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
creationTime: new Date('2023-06-15'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
partyType: PartyType.Customer,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
export const mockBusinessPartyNew: BusinessParty = {
|
||||
id: "",
|
||||
code: "",
|
||||
supplierType: SupplierTypeEnum.Both,
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
id: '',
|
||||
code: '',
|
||||
supplierType: SupplierTypeEnum.ServiceProvider,
|
||||
name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
address: {
|
||||
street: "",
|
||||
city: "",
|
||||
state: "",
|
||||
postalCode: "",
|
||||
country: "",
|
||||
street: '',
|
||||
city: '',
|
||||
state: '',
|
||||
postalCode: '',
|
||||
country: '',
|
||||
},
|
||||
taxNumber: "",
|
||||
taxNumber: '',
|
||||
paymentTerms: PaymentTerms.Cash,
|
||||
currency: "TRY",
|
||||
cardNumber: "",
|
||||
currency: 'TRY',
|
||||
cardNumber: '',
|
||||
cardType: SupplierCardTypeEnum.Standard,
|
||||
validTo: new Date(),
|
||||
validFrom: new Date(),
|
||||
|
|
@ -521,4 +518,4 @@ export const mockBusinessPartyNew: BusinessParty = {
|
|||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
partyType: PartyType.Supplier,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
import { FiCheck, CheckStatusEnum, CheckTypeEnum } from "../types/fi";
|
||||
import { mockCurrentAccounts } from "./mockCurrentAccounts";
|
||||
import { FiCheck, CheckStatusEnum, TypeEnum } from '../types/fi'
|
||||
import { mockCurrentAccounts } from './mockCurrentAccounts'
|
||||
|
||||
export const mockChecks: FiCheck[] = [
|
||||
{
|
||||
id: "1",
|
||||
checkNumber: "CHK-001",
|
||||
bankName: "İş Bankası",
|
||||
branchName: "Levent Şubesi",
|
||||
accountNumber: "1234567890",
|
||||
type: CheckTypeEnum.Received,
|
||||
drawerName: "XYZ Müşteri A.Ş.",
|
||||
payeeName: "ABC Şirket",
|
||||
issueDate: new Date("2024-01-15"),
|
||||
dueDate: new Date("2024-02-15"),
|
||||
id: '1',
|
||||
checkNumber: 'CHK-001',
|
||||
bankName: 'İş Bankası',
|
||||
branchName: 'Levent Şubesi',
|
||||
accountNumber: '1234567890',
|
||||
type: TypeEnum.Received,
|
||||
drawerName: 'XYZ Müşteri A.Ş.',
|
||||
payeeName: 'ABC Şirket',
|
||||
issueDate: new Date('2024-01-15'),
|
||||
dueDate: new Date('2024-02-15'),
|
||||
amount: 25000,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: CheckStatusEnum.InHand,
|
||||
currentAccountId: "1",
|
||||
currentAccount: mockCurrentAccounts.find((ca) => ca.id === "1"),
|
||||
creationTime: new Date("2024-01-15"),
|
||||
lastModificationTime: new Date("2024-01-15"),
|
||||
currentAccountId: '1',
|
||||
currentAccount: mockCurrentAccounts.find((ca) => ca.id === '1'),
|
||||
creationTime: new Date('2024-01-15'),
|
||||
lastModificationTime: new Date('2024-01-15'),
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
checkNumber: "CHK-002",
|
||||
bankName: "Garanti BBVA",
|
||||
branchName: "Şişli Şubesi",
|
||||
accountNumber: "9876543210",
|
||||
type: CheckTypeEnum.Issued,
|
||||
drawerName: "ABC Şirket",
|
||||
payeeName: "Tedarikçi Ltd.",
|
||||
issueDate: new Date("2024-01-10"),
|
||||
dueDate: new Date("2024-02-10"),
|
||||
id: '2',
|
||||
checkNumber: 'CHK-002',
|
||||
bankName: 'Garanti BBVA',
|
||||
branchName: 'Şişli Şubesi',
|
||||
accountNumber: '9876543210',
|
||||
type: TypeEnum.Issued,
|
||||
drawerName: 'ABC Şirket',
|
||||
payeeName: 'Tedarikçi Ltd.',
|
||||
issueDate: new Date('2024-01-10'),
|
||||
dueDate: new Date('2024-02-10'),
|
||||
amount: 15000,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: CheckStatusEnum.Deposited,
|
||||
bankingDate: new Date("2024-01-20"),
|
||||
currentAccountId: "2",
|
||||
currentAccount: mockCurrentAccounts.find((ca) => ca.id === "2"),
|
||||
creationTime: new Date("2024-01-10"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
bankingDate: new Date('2024-01-20'),
|
||||
currentAccountId: '2',
|
||||
currentAccount: mockCurrentAccounts.find((ca) => ca.id === '2'),
|
||||
creationTime: new Date('2024-01-10'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
},
|
||||
];
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,80 +1,80 @@
|
|||
import { PsProjectCostTracking } from "../types/ps";
|
||||
import { ProjectCostTrackingStatus, PsProjectCostTracking } from '../types/ps'
|
||||
|
||||
export const mockProjectCostTracking: PsProjectCostTracking[] = [
|
||||
{
|
||||
id: "1",
|
||||
projectId: "1",
|
||||
projectName: "ERP Sistemi Geliştirme",
|
||||
projectCode: "PRJ-2024-001",
|
||||
plannedBudget: 500000,
|
||||
actualCost: 325000,
|
||||
remainingBudget: 175000,
|
||||
plannedStartDate: new Date("2024-01-15"),
|
||||
plannedEndDate: new Date("2024-12-31"),
|
||||
actualStartDate: new Date("2024-01-20"),
|
||||
actualEndDate: undefined,
|
||||
plannedDuration: 351,
|
||||
actualDuration: 300,
|
||||
progress: 65,
|
||||
status: "ON_TRACK",
|
||||
currency: "TRY",
|
||||
lastUpdated: new Date("2024-11-25"),
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
projectId: "2",
|
||||
projectName: "Mobil Uygulama Geliştirme",
|
||||
projectCode: "PRJ-2024-002",
|
||||
plannedBudget: 250000,
|
||||
actualCost: 200000,
|
||||
remainingBudget: 50000,
|
||||
plannedStartDate: new Date("2024-03-01"),
|
||||
plannedEndDate: new Date("2024-08-31"),
|
||||
actualStartDate: new Date("2024-03-15"),
|
||||
actualEndDate: undefined,
|
||||
plannedDuration: 184,
|
||||
actualDuration: 200,
|
||||
progress: 80,
|
||||
status: "AT_RISK",
|
||||
currency: "TRY",
|
||||
lastUpdated: new Date("2024-11-20"),
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
projectId: "3",
|
||||
projectName: "Web Sitesi Yenileme",
|
||||
projectCode: "PRJ-2024-003",
|
||||
plannedBudget: 150000,
|
||||
actualCost: 180000,
|
||||
remainingBudget: -30000,
|
||||
plannedStartDate: new Date("2024-02-01"),
|
||||
plannedEndDate: new Date("2024-06-30"),
|
||||
actualStartDate: new Date("2024-02-10"),
|
||||
actualEndDate: new Date("2024-07-15"),
|
||||
plannedDuration: 150,
|
||||
actualDuration: 156,
|
||||
progress: 100,
|
||||
status: "COMPLETED",
|
||||
currency: "TRY",
|
||||
lastUpdated: new Date("2024-07-15"),
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
projectId: "4",
|
||||
projectName: "Veri Analizi Platformu",
|
||||
projectCode: "PRJ-2024-004",
|
||||
plannedBudget: 400000,
|
||||
actualCost: 120000,
|
||||
remainingBudget: 280000,
|
||||
plannedStartDate: new Date("2024-06-01"),
|
||||
plannedEndDate: new Date("2024-12-31"),
|
||||
actualStartDate: new Date("2024-06-15"),
|
||||
actualEndDate: undefined,
|
||||
plannedDuration: 214,
|
||||
actualDuration: 163,
|
||||
progress: 30,
|
||||
status: "DELAYED",
|
||||
currency: "TRY",
|
||||
lastUpdated: new Date("2024-11-22"),
|
||||
},
|
||||
];
|
||||
{
|
||||
id: '1',
|
||||
projectId: '1',
|
||||
projectName: 'ERP Sistemi Geliştirme',
|
||||
projectCode: 'PRJ-2024-001',
|
||||
plannedBudget: 500000,
|
||||
actualCost: 325000,
|
||||
remainingBudget: 175000,
|
||||
plannedStartDate: new Date('2024-01-15'),
|
||||
plannedEndDate: new Date('2024-12-31'),
|
||||
actualStartDate: new Date('2024-01-20'),
|
||||
actualEndDate: undefined,
|
||||
plannedDuration: 351,
|
||||
actualDuration: 300,
|
||||
progress: 65,
|
||||
status: ProjectCostTrackingStatus.OnTrack,
|
||||
currency: 'TRY',
|
||||
lastUpdated: new Date('2024-11-25'),
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
projectId: '2',
|
||||
projectName: 'Mobil Uygulama Geliştirme',
|
||||
projectCode: 'PRJ-2024-002',
|
||||
plannedBudget: 250000,
|
||||
actualCost: 200000,
|
||||
remainingBudget: 50000,
|
||||
plannedStartDate: new Date('2024-03-01'),
|
||||
plannedEndDate: new Date('2024-08-31'),
|
||||
actualStartDate: new Date('2024-03-15'),
|
||||
actualEndDate: undefined,
|
||||
plannedDuration: 184,
|
||||
actualDuration: 200,
|
||||
progress: 80,
|
||||
status: ProjectCostTrackingStatus.AtRisk,
|
||||
currency: 'TRY',
|
||||
lastUpdated: new Date('2024-11-20'),
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
projectId: '3',
|
||||
projectName: 'Web Sitesi Yenileme',
|
||||
projectCode: 'PRJ-2024-003',
|
||||
plannedBudget: 150000,
|
||||
actualCost: 180000,
|
||||
remainingBudget: -30000,
|
||||
plannedStartDate: new Date('2024-02-01'),
|
||||
plannedEndDate: new Date('2024-06-30'),
|
||||
actualStartDate: new Date('2024-02-10'),
|
||||
actualEndDate: new Date('2024-07-15'),
|
||||
plannedDuration: 150,
|
||||
actualDuration: 156,
|
||||
progress: 100,
|
||||
status: ProjectCostTrackingStatus.Completed,
|
||||
currency: 'TRY',
|
||||
lastUpdated: new Date('2024-07-15'),
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
projectId: '4',
|
||||
projectName: 'Veri Analizi Platformu',
|
||||
projectCode: 'PRJ-2024-004',
|
||||
plannedBudget: 400000,
|
||||
actualCost: 120000,
|
||||
remainingBudget: 280000,
|
||||
plannedStartDate: new Date('2024-06-01'),
|
||||
plannedEndDate: new Date('2024-12-31'),
|
||||
actualStartDate: new Date('2024-06-15'),
|
||||
actualEndDate: undefined,
|
||||
plannedDuration: 214,
|
||||
actualDuration: 163,
|
||||
progress: 30,
|
||||
status: ProjectCostTrackingStatus.Delayed,
|
||||
currency: 'TRY',
|
||||
lastUpdated: new Date('2024-11-22'),
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,180 +1,164 @@
|
|||
import { PhaseStatusEnum, PsProjectPhase } from "../types/ps";
|
||||
import { mockMaintenanceTeams } from "./mockMaintenanceTeams";
|
||||
import { mockProjects } from "./mockProjects";
|
||||
import { PhaseCategoryEnum, PhaseStatusEnum, PsProjectPhase } from '../types/ps'
|
||||
import { mockMaintenanceTeams } from './mockMaintenanceTeams'
|
||||
import { mockProjects } from './mockProjects'
|
||||
|
||||
export const mockProjectPhases: PsProjectPhase[] = [
|
||||
{
|
||||
id: "1",
|
||||
code: "PH-001",
|
||||
name: "Analiz ve Tasarım",
|
||||
description: "Sistem analizi ve tasarım dokümantasyonu hazırlanması",
|
||||
projectId: "1",
|
||||
project: mockProjects.find((p) => p.id === "1")!,
|
||||
id: '1',
|
||||
code: 'PH-001',
|
||||
name: 'Analiz ve Tasarım',
|
||||
description: 'Sistem analizi ve tasarım dokümantasyonu hazırlanması',
|
||||
projectId: '1',
|
||||
project: mockProjects.find((p) => p.id === '1')!,
|
||||
status: PhaseStatusEnum.Completed,
|
||||
startDate: new Date("2024-01-15"),
|
||||
endDate: new Date("2024-02-28"),
|
||||
actualStartDate: new Date("2024-01-15"),
|
||||
actualEndDate: new Date("2024-02-25"),
|
||||
startDate: new Date('2024-01-15'),
|
||||
endDate: new Date('2024-02-28'),
|
||||
actualStartDate: new Date('2024-01-15'),
|
||||
actualEndDate: new Date('2024-02-25'),
|
||||
budget: 150000,
|
||||
actualCost: 145000,
|
||||
progress: 100,
|
||||
milestones: 4,
|
||||
completedMilestones: 4,
|
||||
assignedTeams: [
|
||||
mockMaintenanceTeams.find((t) => t.id === "1")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '1')!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||
],
|
||||
deliverables: [
|
||||
"Sistem Analiz Raporu",
|
||||
"Teknik Tasarım Dokümanı",
|
||||
"UI/UX Tasarımları",
|
||||
],
|
||||
risks: ["Gereksinim değişiklikleri"],
|
||||
category: "Planning",
|
||||
deliverables: ['Sistem Analiz Raporu', 'Teknik Tasarım Dokümanı', 'UI/UX Tasarımları'],
|
||||
risks: ['Gereksinim değişiklikleri'],
|
||||
category: PhaseCategoryEnum.Planning,
|
||||
sequence: 0,
|
||||
tasks: [],
|
||||
isActive: false,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
code: "PH-002",
|
||||
name: "Geliştirme - Faz 1",
|
||||
description: "Backend altyapısı ve temel modüllerin geliştirilmesi",
|
||||
projectId: "1",
|
||||
project: mockProjects.find((p) => p.id === "1")!,
|
||||
id: '2',
|
||||
code: 'PH-002',
|
||||
name: 'Geliştirme - Faz 1',
|
||||
description: 'Backend altyapısı ve temel modüllerin geliştirilmesi',
|
||||
projectId: '1',
|
||||
project: mockProjects.find((p) => p.id === '1')!,
|
||||
status: PhaseStatusEnum.Cancelled,
|
||||
startDate: new Date("2024-03-01"),
|
||||
endDate: new Date("2024-05-15"),
|
||||
actualStartDate: new Date("2024-03-01"),
|
||||
actualEndDate: new Date("2024-05-10"),
|
||||
startDate: new Date('2024-03-01'),
|
||||
endDate: new Date('2024-05-15'),
|
||||
actualStartDate: new Date('2024-03-01'),
|
||||
actualEndDate: new Date('2024-05-10'),
|
||||
budget: 400000,
|
||||
actualCost: 280000,
|
||||
progress: 70,
|
||||
milestones: 6,
|
||||
completedMilestones: 4,
|
||||
assignedTeams: [
|
||||
mockMaintenanceTeams.find((t) => t.id === "1")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '1')!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||
],
|
||||
deliverables: ["API Framework", "Veritabanı Şeması", "Güvenlik Modülü"],
|
||||
risks: ["Performans sorunları", "Üçüncü parti entegrasyon gecikmeleri"],
|
||||
category: "Development",
|
||||
deliverables: ['API Framework', 'Veritabanı Şeması', 'Güvenlik Modülü'],
|
||||
risks: ['Performans sorunları', 'Üçüncü parti entegrasyon gecikmeleri'],
|
||||
category: PhaseCategoryEnum.Development,
|
||||
sequence: 0,
|
||||
tasks: [],
|
||||
isActive: false,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
code: "PH-003",
|
||||
name: "Geliştirme - Faz 2",
|
||||
description: "Frontend geliştirme ve kullanıcı arayüzleri",
|
||||
projectId: "1",
|
||||
project: mockProjects.find((p) => p.id === "1")!,
|
||||
id: '3',
|
||||
code: 'PH-003',
|
||||
name: 'Geliştirme - Faz 2',
|
||||
description: 'Frontend geliştirme ve kullanıcı arayüzleri',
|
||||
projectId: '1',
|
||||
project: mockProjects.find((p) => p.id === '1')!,
|
||||
status: PhaseStatusEnum.NotStarted,
|
||||
startDate: new Date("2024-04-15"),
|
||||
endDate: new Date("2024-07-30"),
|
||||
startDate: new Date('2024-04-15'),
|
||||
endDate: new Date('2024-07-30'),
|
||||
budget: 350000,
|
||||
actualCost: 0,
|
||||
progress: 0,
|
||||
milestones: 5,
|
||||
completedMilestones: 0,
|
||||
assignedTeams: [
|
||||
mockMaintenanceTeams.find((t) => t.id === "1")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '1')!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||
],
|
||||
deliverables: [
|
||||
"React Bileşenleri",
|
||||
"Responsive Tasarım",
|
||||
"Mobil Uyumluluk",
|
||||
],
|
||||
risks: ["Tarayıcı uyumluluk sorunları", "Performans optimizasyonu"],
|
||||
category: "Development",
|
||||
deliverables: ['React Bileşenleri', 'Responsive Tasarım', 'Mobil Uyumluluk'],
|
||||
risks: ['Tarayıcı uyumluluk sorunları', 'Performans optimizasyonu'],
|
||||
category: PhaseCategoryEnum.Development,
|
||||
sequence: 0,
|
||||
tasks: [],
|
||||
isActive: false,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
code: "PH-004",
|
||||
name: "Test ve Kalite Güvence",
|
||||
description: "Kapsamlı test süreçleri ve kalite kontrolleri",
|
||||
projectId: "2",
|
||||
project: mockProjects.find((p) => p.id === "2")!,
|
||||
id: '4',
|
||||
code: 'PH-004',
|
||||
name: 'Test ve Kalite Güvence',
|
||||
description: 'Kapsamlı test süreçleri ve kalite kontrolleri',
|
||||
projectId: '2',
|
||||
project: mockProjects.find((p) => p.id === '2')!,
|
||||
status: PhaseStatusEnum.NotStarted,
|
||||
startDate: new Date("2024-07-01"),
|
||||
endDate: new Date("2024-09-15"),
|
||||
startDate: new Date('2024-07-01'),
|
||||
endDate: new Date('2024-09-15'),
|
||||
budget: 120000,
|
||||
actualCost: 0,
|
||||
progress: 0,
|
||||
milestones: 3,
|
||||
completedMilestones: 0,
|
||||
assignedTeams: [
|
||||
mockMaintenanceTeams.find((t) => t.id === "3")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === "4")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '3')!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '4')!.name,
|
||||
],
|
||||
deliverables: [
|
||||
"Test Senaryoları",
|
||||
"Otomatik Test Süitleri",
|
||||
"Kalite Raporu",
|
||||
],
|
||||
risks: ["Kritik hataların geç tespit edilmesi"],
|
||||
category: "Testing",
|
||||
deliverables: ['Test Senaryoları', 'Otomatik Test Süitleri', 'Kalite Raporu'],
|
||||
risks: ['Kritik hataların geç tespit edilmesi'],
|
||||
category: PhaseCategoryEnum.Testing,
|
||||
sequence: 0,
|
||||
tasks: [],
|
||||
isActive: false,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
code: "PH-005",
|
||||
name: "Deployment ve Go-Live",
|
||||
description: "Üretime alma ve kullanıcı eğitimleri",
|
||||
projectId: "2",
|
||||
project: mockProjects.find((p) => p.id === "2")!,
|
||||
id: '5',
|
||||
code: 'PH-005',
|
||||
name: 'Deployment ve Go-Live',
|
||||
description: 'Üretime alma ve kullanıcı eğitimleri',
|
||||
projectId: '2',
|
||||
project: mockProjects.find((p) => p.id === '2')!,
|
||||
status: PhaseStatusEnum.NotStarted,
|
||||
startDate: new Date("2024-09-15"),
|
||||
endDate: new Date("2024-10-31"),
|
||||
startDate: new Date('2024-09-15'),
|
||||
endDate: new Date('2024-10-31'),
|
||||
budget: 80000,
|
||||
actualCost: 0,
|
||||
progress: 0,
|
||||
milestones: 2,
|
||||
completedMilestones: 0,
|
||||
assignedTeams: [
|
||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === "4")!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||
mockMaintenanceTeams.find((t) => t.id === '4')!.name,
|
||||
],
|
||||
deliverables: [
|
||||
"Prodüksiyon Ortamı",
|
||||
"Kullanıcı Eğitimleri",
|
||||
"Dokümentasyon",
|
||||
],
|
||||
risks: ["Sistem kesintileri", "Kullanıcı adaptasyon sorunları"],
|
||||
category: "Deployment",
|
||||
deliverables: ['Prodüksiyon Ortamı', 'Kullanıcı Eğitimleri', 'Dokümentasyon'],
|
||||
risks: ['Sistem kesintileri', 'Kullanıcı adaptasyon sorunları'],
|
||||
category: PhaseCategoryEnum.Deployment,
|
||||
sequence: 0,
|
||||
tasks: [],
|
||||
isActive: false,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
code: "PH-006",
|
||||
name: "Mobil UI Tasarımı",
|
||||
description: "Mobil uygulama kullanıcı arayüzü tasarımı",
|
||||
projectId: "2",
|
||||
project: mockProjects.find((p) => p.id === "2")!,
|
||||
id: '6',
|
||||
code: 'PH-006',
|
||||
name: 'Mobil UI Tasarımı',
|
||||
description: 'Mobil uygulama kullanıcı arayüzü tasarımı',
|
||||
projectId: '2',
|
||||
project: mockProjects.find((p) => p.id === '2')!,
|
||||
status: PhaseStatusEnum.OnHold,
|
||||
startDate: new Date("2024-03-01"),
|
||||
endDate: new Date("2024-04-15"),
|
||||
actualStartDate: new Date("2024-03-05"),
|
||||
startDate: new Date('2024-03-01'),
|
||||
endDate: new Date('2024-04-15'),
|
||||
actualStartDate: new Date('2024-03-05'),
|
||||
budget: 75000,
|
||||
actualCost: 25000,
|
||||
progress: 35,
|
||||
milestones: 3,
|
||||
completedMilestones: 1,
|
||||
assignedTeams: [mockMaintenanceTeams.find((t) => t.id === "1")!.name],
|
||||
deliverables: ["Wireframe'ler", "Mobil Tasarım Kılavuzu", "Prototype"],
|
||||
risks: ["Platformlar arası tutarlılık sorunları"],
|
||||
category: "Design",
|
||||
assignedTeams: [mockMaintenanceTeams.find((t) => t.id === '1')!.name],
|
||||
deliverables: ["Wireframe'ler", 'Mobil Tasarım Kılavuzu', 'Prototype'],
|
||||
risks: ['Platformlar arası tutarlılık sorunları'],
|
||||
category: PhaseCategoryEnum.Design,
|
||||
sequence: 0,
|
||||
tasks: [],
|
||||
isActive: false,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,40 +1,40 @@
|
|||
import { NoteStatusEnum, NoteTypeEnum, PromissoryNote } from "../types/fi";
|
||||
import { mockCurrentAccounts } from "./mockCurrentAccounts";
|
||||
import { NoteStatusEnum, PromissoryNote, TypeEnum } from '../types/fi'
|
||||
import { mockCurrentAccounts } from './mockCurrentAccounts'
|
||||
|
||||
export const mockPromissoryNotes: PromissoryNote[] = [
|
||||
{
|
||||
id: "1",
|
||||
noteNumber: "NOT-001",
|
||||
type: NoteTypeEnum.Received,
|
||||
drawerName: "Müşteri A.Ş.",
|
||||
payeeName: "ABC Şirket",
|
||||
issueDate: new Date("2024-01-20"),
|
||||
dueDate: new Date("2024-03-20"),
|
||||
id: '1',
|
||||
noteNumber: 'NOT-001',
|
||||
type: TypeEnum.Received,
|
||||
drawerName: 'Müşteri A.Ş.',
|
||||
payeeName: 'ABC Şirket',
|
||||
issueDate: new Date('2024-01-20'),
|
||||
dueDate: new Date('2024-03-20'),
|
||||
amount: 50000,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: NoteStatusEnum.InHand,
|
||||
location: "Ana Kasa",
|
||||
currentAccountId: "1",
|
||||
currentAccount: mockCurrentAccounts.find((acc) => acc.id === "1"),
|
||||
creationTime: new Date("2024-01-20"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
location: 'Ana Kasa',
|
||||
currentAccountId: '1',
|
||||
currentAccount: mockCurrentAccounts.find((acc) => acc.id === '1'),
|
||||
creationTime: new Date('2024-01-20'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
noteNumber: "NOT-002",
|
||||
type: NoteTypeEnum.Issued,
|
||||
drawerName: "ABC Şirket",
|
||||
payeeName: "Kefil A.Ş.",
|
||||
issueDate: new Date("2024-01-05"),
|
||||
dueDate: new Date("2024-03-05"),
|
||||
id: '2',
|
||||
noteNumber: 'NOT-002',
|
||||
type: TypeEnum.Issued,
|
||||
drawerName: 'ABC Şirket',
|
||||
payeeName: 'Kefil A.Ş.',
|
||||
issueDate: new Date('2024-01-05'),
|
||||
dueDate: new Date('2024-03-05'),
|
||||
amount: 30000,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: NoteStatusEnum.Collected,
|
||||
location: "Banka",
|
||||
collectionDate: new Date("2024-01-25"),
|
||||
currentAccountId: "2",
|
||||
currentAccount: mockCurrentAccounts.find((acc) => acc.id === "2"),
|
||||
creationTime: new Date("2024-01-05"),
|
||||
lastModificationTime: new Date("2024-01-25"),
|
||||
location: 'Banka',
|
||||
collectionDate: new Date('2024-01-25'),
|
||||
currentAccountId: '2',
|
||||
currentAccount: mockCurrentAccounts.find((acc) => acc.id === '2'),
|
||||
creationTime: new Date('2024-01-05'),
|
||||
lastModificationTime: new Date('2024-01-25'),
|
||||
},
|
||||
];
|
||||
]
|
||||
|
|
|
|||
28
ui/src/mocks/mockWorkCenterMachineTypes.ts
Normal file
28
ui/src/mocks/mockWorkCenterMachineTypes.ts
Normal 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,
|
||||
},
|
||||
]
|
||||
|
|
@ -1,42 +1,39 @@
|
|||
import {
|
||||
CriticalityLevelEnum,
|
||||
PmWorkCenter,
|
||||
WorkCenterStatusEnum,
|
||||
} from "../types/pm";
|
||||
import { mockWorkCenterTypes } from "./mockWorkCenterTypes";
|
||||
import { CriticalityLevelEnum, PmWorkCenter, WorkCenterStatusEnum } from '../types/pm'
|
||||
import { mockWorkCenterMachineTypes } from './mockWorkCenterMachineTypes'
|
||||
import { mockWorkCenterTypes } from './mockWorkCenterTypes'
|
||||
|
||||
export const mockWorkCenters: PmWorkCenter[] = [
|
||||
{
|
||||
id: "1",
|
||||
code: "CNC-001",
|
||||
name: "CNC Torna Tezgahı",
|
||||
description: "Yüksek hassasiyetli CNC torna tezgahı",
|
||||
workCenterId: "1",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "1")!,
|
||||
manufacturer: "HAAS Automation",
|
||||
model: "ST-30",
|
||||
serialNumber: "SN123456789",
|
||||
installationDate: new Date("2022-03-15"),
|
||||
warrantyExpiry: new Date("2025-03-15"),
|
||||
location: "Atölye A - Hat 1",
|
||||
departmentId: "1",
|
||||
id: '1',
|
||||
code: 'CNC-001',
|
||||
name: 'CNC Torna Tezgahı',
|
||||
description: 'Yüksek hassasiyetli CNC torna tezgahı',
|
||||
workCenterId: '1',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '1')!,
|
||||
manufacturer: 'HAAS Automation',
|
||||
model: 'ST-30',
|
||||
serialNumber: 'SN123456789',
|
||||
installationDate: new Date('2022-03-15'),
|
||||
warrantyExpiry: new Date('2025-03-15'),
|
||||
location: 'Atölye A - Hat 1',
|
||||
departmentId: '1',
|
||||
status: WorkCenterStatusEnum.Operational,
|
||||
criticality: CriticalityLevelEnum.High,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC001",
|
||||
workCenterId: "EQP001",
|
||||
specificationName: "Max Çap",
|
||||
specificationValue: "300",
|
||||
unit: "mm",
|
||||
id: 'SPEC001',
|
||||
workCenterId: 'EQP001',
|
||||
specificationName: 'Max Çap',
|
||||
specificationValue: '300',
|
||||
unit: 'mm',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC002",
|
||||
workCenterId: "EQP001",
|
||||
specificationName: "Motor Gücü",
|
||||
specificationValue: "15",
|
||||
unit: "kW",
|
||||
id: 'SPEC002',
|
||||
workCenterId: 'EQP001',
|
||||
specificationName: 'Motor Gücü',
|
||||
specificationValue: '15',
|
||||
unit: 'kW',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -44,44 +41,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2022-03-15"),
|
||||
lastModificationTime: new Date("2024-01-15"),
|
||||
creationTime: new Date('2022-03-15'),
|
||||
lastModificationTime: new Date('2024-01-15'),
|
||||
capacity: 8,
|
||||
costPerHour: 75,
|
||||
setupTime: 15,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '1',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
code: "COMP-001",
|
||||
name: "Hava Kompresörü",
|
||||
description: "Endüstriyel hava kompresörü sistemi",
|
||||
workCenterId: "2",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "2")!,
|
||||
manufacturer: "Atlas Copco",
|
||||
model: "GA55VSD+",
|
||||
serialNumber: "AC987654321",
|
||||
installationDate: new Date("2021-08-20"),
|
||||
warrantyExpiry: new Date("2024-08-20"),
|
||||
location: "Kompresör Odası",
|
||||
departmentId: "2",
|
||||
id: '2',
|
||||
code: 'COMP-001',
|
||||
name: 'Hava Kompresörü',
|
||||
description: 'Endüstriyel hava kompresörü sistemi',
|
||||
workCenterId: '2',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '2')!,
|
||||
manufacturer: 'Atlas Copco',
|
||||
model: 'GA55VSD+',
|
||||
serialNumber: 'AC987654321',
|
||||
installationDate: new Date('2021-08-20'),
|
||||
warrantyExpiry: new Date('2024-08-20'),
|
||||
location: 'Kompresör Odası',
|
||||
departmentId: '2',
|
||||
status: WorkCenterStatusEnum.UnderMaintenance,
|
||||
criticality: CriticalityLevelEnum.Critical,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC003",
|
||||
workCenterId: "EQP002",
|
||||
specificationName: "Basınç",
|
||||
specificationValue: "8.5",
|
||||
unit: "bar",
|
||||
id: 'SPEC003',
|
||||
workCenterId: 'EQP002',
|
||||
specificationName: 'Basınç',
|
||||
specificationValue: '8.5',
|
||||
unit: 'bar',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC004",
|
||||
workCenterId: "EQP002",
|
||||
specificationName: "Kapasite",
|
||||
specificationValue: "55",
|
||||
unit: "kW",
|
||||
id: 'SPEC004',
|
||||
workCenterId: 'EQP002',
|
||||
specificationName: 'Kapasite',
|
||||
specificationValue: '55',
|
||||
unit: 'kW',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -89,43 +87,44 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2021-08-20"),
|
||||
lastModificationTime: new Date("2024-02-01"),
|
||||
creationTime: new Date('2021-08-20'),
|
||||
lastModificationTime: new Date('2024-02-01'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '2',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '2')!,
|
||||
capacity: 8,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
code: "CONV-001",
|
||||
name: "Konveyör Sistemi",
|
||||
description: "Ana hat konveyör sistemi",
|
||||
workCenterId: "3",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "3")!,
|
||||
manufacturer: "Siemens",
|
||||
model: "SIMATIC S7-1500",
|
||||
serialNumber: "SM112233445",
|
||||
installationDate: new Date("2020-11-10"),
|
||||
location: "Ana Üretim Hattı",
|
||||
departmentId: "3",
|
||||
id: '3',
|
||||
code: 'CONV-001',
|
||||
name: 'Konveyör Sistemi',
|
||||
description: 'Ana hat konveyör sistemi',
|
||||
workCenterId: '3',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '3')!,
|
||||
manufacturer: 'Siemens',
|
||||
model: 'SIMATIC S7-1500',
|
||||
serialNumber: 'SM112233445',
|
||||
installationDate: new Date('2020-11-10'),
|
||||
location: 'Ana Üretim Hattı',
|
||||
departmentId: '3',
|
||||
status: WorkCenterStatusEnum.OutOfOrder,
|
||||
criticality: CriticalityLevelEnum.Medium,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC005",
|
||||
workCenterId: "EQP003",
|
||||
specificationName: "Hız",
|
||||
specificationValue: "2.5",
|
||||
unit: "m/s",
|
||||
id: 'SPEC005',
|
||||
workCenterId: 'EQP003',
|
||||
specificationName: 'Hız',
|
||||
specificationValue: '2.5',
|
||||
unit: 'm/s',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC006",
|
||||
workCenterId: "EQP003",
|
||||
specificationName: "Yük Kapasitesi",
|
||||
specificationValue: "500",
|
||||
unit: "kg",
|
||||
id: 'SPEC006',
|
||||
workCenterId: 'EQP003',
|
||||
specificationName: 'Yük Kapasitesi',
|
||||
specificationValue: '500',
|
||||
unit: 'kg',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -133,44 +132,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2020-11-10"),
|
||||
lastModificationTime: new Date("2024-02-05"),
|
||||
creationTime: new Date('2020-11-10'),
|
||||
lastModificationTime: new Date('2024-02-05'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '3',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '3')!,
|
||||
capacity: 8,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
code: "KELD-001",
|
||||
name: "Kaynak Makinesi",
|
||||
description: "Otomatik robot kaynak sistemi",
|
||||
workCenterId: "4",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
||||
manufacturer: "KUKA",
|
||||
model: "KR 60-3",
|
||||
serialNumber: "KU556677889",
|
||||
installationDate: new Date("2023-01-15"),
|
||||
warrantyExpiry: new Date("2026-01-15"),
|
||||
location: "Kaynak Atölyesi",
|
||||
departmentId: "4",
|
||||
id: '4',
|
||||
code: 'KELD-001',
|
||||
name: 'Kaynak Makinesi',
|
||||
description: 'Otomatik robot kaynak sistemi',
|
||||
workCenterId: '4',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||
manufacturer: 'KUKA',
|
||||
model: 'KR 60-3',
|
||||
serialNumber: 'KU556677889',
|
||||
installationDate: new Date('2023-01-15'),
|
||||
warrantyExpiry: new Date('2026-01-15'),
|
||||
location: 'Kaynak Atölyesi',
|
||||
departmentId: '4',
|
||||
status: WorkCenterStatusEnum.Operational,
|
||||
criticality: CriticalityLevelEnum.High,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC007",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Erişim Mesafesi",
|
||||
specificationValue: "2033",
|
||||
unit: "mm",
|
||||
id: 'SPEC007',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Erişim Mesafesi',
|
||||
specificationValue: '2033',
|
||||
unit: 'mm',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC008",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Taşıma Kapasitesi",
|
||||
specificationValue: "60",
|
||||
unit: "kg",
|
||||
id: 'SPEC008',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Taşıma Kapasitesi',
|
||||
specificationValue: '60',
|
||||
unit: 'kg',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -178,44 +178,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-01-15"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
creationTime: new Date('2023-01-15'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '3',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '3')!,
|
||||
capacity: 8,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
code: "WELL-001",
|
||||
name: "Yıkama Makinesi",
|
||||
description: "Otomatik robot kaynak sistemi",
|
||||
workCenterId: "4",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
||||
manufacturer: "KUKA",
|
||||
model: "KR 60-3",
|
||||
serialNumber: "KU556677889",
|
||||
installationDate: new Date("2023-01-15"),
|
||||
warrantyExpiry: new Date("2026-01-15"),
|
||||
location: "Kaynak Atölyesi",
|
||||
departmentId: "4",
|
||||
id: '5',
|
||||
code: 'WELL-001',
|
||||
name: 'Yıkama Makinesi',
|
||||
description: 'Otomatik robot kaynak sistemi',
|
||||
workCenterId: '4',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||
manufacturer: 'KUKA',
|
||||
model: 'KR 60-3',
|
||||
serialNumber: 'KU556677889',
|
||||
installationDate: new Date('2023-01-15'),
|
||||
warrantyExpiry: new Date('2026-01-15'),
|
||||
location: 'Kaynak Atölyesi',
|
||||
departmentId: '4',
|
||||
status: WorkCenterStatusEnum.Operational,
|
||||
criticality: CriticalityLevelEnum.High,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC007",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Erişim Mesafesi",
|
||||
specificationValue: "2033",
|
||||
unit: "mm",
|
||||
id: 'SPEC007',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Erişim Mesafesi',
|
||||
specificationValue: '2033',
|
||||
unit: 'mm',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC008",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Taşıma Kapasitesi",
|
||||
specificationValue: "60",
|
||||
unit: "kg",
|
||||
id: 'SPEC008',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Taşıma Kapasitesi',
|
||||
specificationValue: '60',
|
||||
unit: 'kg',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -223,44 +224,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-01-15"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
creationTime: new Date('2023-01-15'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '4',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '4')!,
|
||||
capacity: 8,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
code: "KELD-001",
|
||||
name: "Ram Makinesi",
|
||||
description: "Otomatik robot kaynak sistemi",
|
||||
workCenterId: "4",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
||||
manufacturer: "KUKA",
|
||||
model: "KR 60-3",
|
||||
serialNumber: "KU556677889",
|
||||
installationDate: new Date("2023-01-15"),
|
||||
warrantyExpiry: new Date("2026-01-15"),
|
||||
location: "Kaynak Atölyesi",
|
||||
departmentId: "4",
|
||||
id: '6',
|
||||
code: 'KELD-001',
|
||||
name: 'Ram Makinesi',
|
||||
description: 'Otomatik robot kaynak sistemi',
|
||||
workCenterId: '4',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||
manufacturer: 'KUKA',
|
||||
model: 'KR 60-3',
|
||||
serialNumber: 'KU556677889',
|
||||
installationDate: new Date('2023-01-15'),
|
||||
warrantyExpiry: new Date('2026-01-15'),
|
||||
location: 'Kaynak Atölyesi',
|
||||
departmentId: '4',
|
||||
status: WorkCenterStatusEnum.Operational,
|
||||
criticality: CriticalityLevelEnum.High,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC007",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Erişim Mesafesi",
|
||||
specificationValue: "2033",
|
||||
unit: "mm",
|
||||
id: 'SPEC007',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Erişim Mesafesi',
|
||||
specificationValue: '2033',
|
||||
unit: 'mm',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC008",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Taşıma Kapasitesi",
|
||||
specificationValue: "60",
|
||||
unit: "kg",
|
||||
id: 'SPEC008',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Taşıma Kapasitesi',
|
||||
specificationValue: '60',
|
||||
unit: 'kg',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -268,44 +270,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-01-15"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
creationTime: new Date('2023-01-15'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '4',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '4')!,
|
||||
capacity: 8,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
code: "WEID-001",
|
||||
name: "Sarma Makinesi",
|
||||
description: "Otomatik robot kaynak sistemi",
|
||||
workCenterId: "4",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
||||
manufacturer: "KUKA",
|
||||
model: "KR 60-3",
|
||||
serialNumber: "KU556677889",
|
||||
installationDate: new Date("2023-01-15"),
|
||||
warrantyExpiry: new Date("2026-01-15"),
|
||||
location: "Kaynak Atölyesi",
|
||||
departmentId: "4",
|
||||
id: '7',
|
||||
code: 'WEID-001',
|
||||
name: 'Sarma Makinesi',
|
||||
description: 'Otomatik robot kaynak sistemi',
|
||||
workCenterId: '4',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||
manufacturer: 'KUKA',
|
||||
model: 'KR 60-3',
|
||||
serialNumber: 'KU556677889',
|
||||
installationDate: new Date('2023-01-15'),
|
||||
warrantyExpiry: new Date('2026-01-15'),
|
||||
location: 'Kaynak Atölyesi',
|
||||
departmentId: '4',
|
||||
status: WorkCenterStatusEnum.Operational,
|
||||
criticality: CriticalityLevelEnum.High,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC007",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Erişim Mesafesi",
|
||||
specificationValue: "2033",
|
||||
unit: "mm",
|
||||
id: 'SPEC007',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Erişim Mesafesi',
|
||||
specificationValue: '2033',
|
||||
unit: 'mm',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC008",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Taşıma Kapasitesi",
|
||||
specificationValue: "60",
|
||||
unit: "kg",
|
||||
id: 'SPEC008',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Taşıma Kapasitesi',
|
||||
specificationValue: '60',
|
||||
unit: 'kg',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -313,44 +316,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-01-15"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
creationTime: new Date('2023-01-15'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '1',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
|
||||
capacity: 8,
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
code: "KEL-001",
|
||||
name: "Robot Kaynak Makinesi",
|
||||
description: "Otomatik robot kaynak sistemi",
|
||||
workCenterId: "4",
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
||||
manufacturer: "KUKA",
|
||||
model: "KR 60-3",
|
||||
serialNumber: "KU556677889",
|
||||
installationDate: new Date("2023-01-15"),
|
||||
warrantyExpiry: new Date("2026-01-15"),
|
||||
location: "Kaynak Atölyesi",
|
||||
departmentId: "4",
|
||||
id: '8',
|
||||
code: 'KEL-001',
|
||||
name: 'Robot Kaynak Makinesi',
|
||||
description: 'Otomatik robot kaynak sistemi',
|
||||
workCenterId: '4',
|
||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||
manufacturer: 'KUKA',
|
||||
model: 'KR 60-3',
|
||||
serialNumber: 'KU556677889',
|
||||
installationDate: new Date('2023-01-15'),
|
||||
warrantyExpiry: new Date('2026-01-15'),
|
||||
location: 'Kaynak Atölyesi',
|
||||
departmentId: '4',
|
||||
status: WorkCenterStatusEnum.Operational,
|
||||
criticality: CriticalityLevelEnum.High,
|
||||
specifications: [
|
||||
{
|
||||
id: "SPEC007",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Erişim Mesafesi",
|
||||
specificationValue: "2033",
|
||||
unit: "mm",
|
||||
id: 'SPEC007',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Erişim Mesafesi',
|
||||
specificationValue: '2033',
|
||||
unit: 'mm',
|
||||
isRequired: true,
|
||||
},
|
||||
{
|
||||
id: "SPEC008",
|
||||
workCenterId: "EQP004",
|
||||
specificationName: "Taşıma Kapasitesi",
|
||||
specificationValue: "60",
|
||||
unit: "kg",
|
||||
id: 'SPEC008',
|
||||
workCenterId: 'EQP004',
|
||||
specificationName: 'Taşıma Kapasitesi',
|
||||
specificationValue: '60',
|
||||
unit: 'kg',
|
||||
isRequired: true,
|
||||
},
|
||||
],
|
||||
|
|
@ -358,11 +362,12 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
|||
workOrders: [],
|
||||
downTimeHistory: [],
|
||||
isActive: true,
|
||||
creationTime: new Date("2023-01-15"),
|
||||
lastModificationTime: new Date("2024-01-20"),
|
||||
creationTime: new Date('2023-01-15'),
|
||||
lastModificationTime: new Date('2024-01-20'),
|
||||
costPerHour: 85,
|
||||
setupTime: 20,
|
||||
machineType: "CNC",
|
||||
machineTypeId: '1',
|
||||
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
|
||||
capacity: 8,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export interface BusinessParty {
|
|||
partyType: PartyType
|
||||
primaryContact?: Contact
|
||||
contacts?: Contact[]
|
||||
industry?: string
|
||||
industry?: BusinessPartyIndustryEnum
|
||||
email?: string
|
||||
phone?: string
|
||||
website?: string
|
||||
|
|
@ -77,6 +77,21 @@ export interface BusinessParty {
|
|||
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 {
|
||||
// İş Ortağı Durumu
|
||||
Prospect = 'PROSPECT', // Potansiyel
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ export interface FiCheck {
|
|||
amount: number
|
||||
currency: string
|
||||
status: CheckStatusEnum
|
||||
type: CheckTypeEnum
|
||||
type: TypeEnum
|
||||
bankingDate?: Date
|
||||
collectionDate?: Date
|
||||
endorsedTo?: string
|
||||
|
|
@ -227,7 +227,7 @@ export interface PromissoryNote {
|
|||
amount: number
|
||||
currency: string
|
||||
status: NoteStatusEnum
|
||||
type: NoteTypeEnum // Received or Issued
|
||||
type: TypeEnum // Received or Issued
|
||||
collectionDate?: Date
|
||||
endorsedTo?: string
|
||||
location?: string
|
||||
|
|
@ -321,7 +321,7 @@ export enum CheckStatusEnum {
|
|||
Cancelled = 'CANCELLED', // İPTAL EDİLDİ
|
||||
}
|
||||
|
||||
export enum CheckTypeEnum {
|
||||
export enum TypeEnum {
|
||||
Received = 'RECEIVED', // ALINAN
|
||||
Issued = 'ISSUED', // VERİLEN
|
||||
}
|
||||
|
|
@ -334,11 +334,6 @@ export enum NoteStatusEnum {
|
|||
Cancelled = 'CANCELLED', // İPTAL EDİLDİ
|
||||
}
|
||||
|
||||
export enum NoteTypeEnum {
|
||||
Received = 'RECEIVED', // Alınan
|
||||
Issued = 'ISSUED', // Verilen
|
||||
}
|
||||
|
||||
export enum WaybillTypeEnum {
|
||||
Outgoing = 'outgoing', // Çıkış İrsaliyesi
|
||||
Incoming = 'incoming', // Giriş İrsaliyesi
|
||||
|
|
|
|||
|
|
@ -758,3 +758,20 @@ export enum QuestionTypeEnum {
|
|||
YesNo = 'YES_NO', // Evet/Hayır
|
||||
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'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -559,9 +559,11 @@ export enum OrderStatusEnum {
|
|||
|
||||
export enum SupplierTypeEnum {
|
||||
// Tedarikçi Türü
|
||||
Material = 'MATERIAL', // Malzeme
|
||||
Service = 'SERVICE', // Hizmet
|
||||
Both = 'BOTH', // Her ikisi
|
||||
Manufacturer = 'MANUFACTURER', // Üretici
|
||||
Distributor = 'DISTRIBUTOR', // Distribütör
|
||||
Wholesaler = 'WHOLESALER', // Toptancı
|
||||
ServiceProvider = 'SERVICE_PROVIDER', // Hizmet Sağlayıcı
|
||||
Other = 'OTHER', // Diğer
|
||||
}
|
||||
|
||||
export enum RequisitionStatusEnum {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ export interface PmWorkCenter {
|
|||
capacity: number
|
||||
costPerHour: number
|
||||
setupTime: number
|
||||
machineType: string
|
||||
machineTypeId: string
|
||||
machineType?: PmMachineType
|
||||
isActive: boolean
|
||||
creationTime: Date
|
||||
lastModificationTime: Date
|
||||
|
|
@ -45,6 +46,14 @@ export interface PmWorkCenterType {
|
|||
isActive: boolean
|
||||
}
|
||||
|
||||
export interface PmMachineType {
|
||||
// Makina Türü
|
||||
id: string
|
||||
code: string
|
||||
name: string
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
export interface PmWorkCenterSpecification {
|
||||
// İş Merkezi / Ekipman Özelliği
|
||||
id: string
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export interface PsProjectPhase {
|
|||
assignedTeams: string[]
|
||||
deliverables: string[]
|
||||
risks: string[]
|
||||
category: string
|
||||
category: PhaseCategoryEnum
|
||||
}
|
||||
|
||||
export interface PsProjectTask {
|
||||
|
|
@ -172,7 +172,7 @@ export interface PsProjectCostTracking {
|
|||
plannedDuration: number // days
|
||||
actualDuration?: number // days
|
||||
progress: number // percentage
|
||||
status: 'ON_TRACK' | 'AT_RISK' | 'DELAYED' | 'COMPLETED'
|
||||
status: ProjectCostTrackingStatus
|
||||
currency: string
|
||||
lastUpdated: Date
|
||||
}
|
||||
|
|
@ -255,6 +255,15 @@ export enum ProjectStatusEnum {
|
|||
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 {
|
||||
// Faz Durumu
|
||||
NotStarted = 'NOT_STARTED', // Başlanmadı
|
||||
|
|
@ -354,3 +363,11 @@ export enum PsDocumentTypeEnum {
|
|||
Manual = 'MANUAL', // Kılavuz
|
||||
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
|
|
@ -1,159 +1,151 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaSave, FaTimes, FaBuilding } from "react-icons/fa";
|
||||
import { BankAccountTypeEnum } from "../../../types/fi";
|
||||
import { BankAccount } from "../../../types/common";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaSave, FaTimes, FaBuilding } from 'react-icons/fa'
|
||||
import { BankAccountTypeEnum } from '../../../types/fi'
|
||||
import { BankAccount } from '../../../types/common'
|
||||
import { getBankAccountTypeText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface BankAccountFormProps {
|
||||
account?: BankAccount;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (account: Partial<BankAccount>) => void;
|
||||
account?: BankAccount
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (account: Partial<BankAccount>) => void
|
||||
}
|
||||
|
||||
const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||
account,
|
||||
isOpen,
|
||||
onClose,
|
||||
onSave,
|
||||
}) => {
|
||||
const BankAccountForm: React.FC<BankAccountFormProps> = ({ account, isOpen, onClose, onSave }) => {
|
||||
const [formData, setFormData] = useState<Partial<BankAccount>>({
|
||||
accountCode: "",
|
||||
bankName: "",
|
||||
branchName: "",
|
||||
accountNumber: "",
|
||||
iban: "",
|
||||
accountCode: '',
|
||||
bankName: '',
|
||||
branchName: '',
|
||||
accountNumber: '',
|
||||
iban: '',
|
||||
accountType: BankAccountTypeEnum.Current,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
balance: 0,
|
||||
overdraftLimit: 0,
|
||||
dailyTransferLimit: 0,
|
||||
contactPerson: "",
|
||||
phone: "",
|
||||
contactPerson: '',
|
||||
phone: '',
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||
|
||||
useEffect(() => {
|
||||
if (account) {
|
||||
setFormData(account);
|
||||
setFormData(account)
|
||||
} else {
|
||||
setFormData({
|
||||
accountCode: "",
|
||||
bankName: "",
|
||||
branchName: "",
|
||||
accountNumber: "",
|
||||
iban: "",
|
||||
accountCode: '',
|
||||
bankName: '',
|
||||
branchName: '',
|
||||
accountNumber: '',
|
||||
iban: '',
|
||||
accountType: BankAccountTypeEnum.Current,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
balance: 0,
|
||||
overdraftLimit: 0,
|
||||
dailyTransferLimit: 0,
|
||||
contactPerson: "",
|
||||
phone: "",
|
||||
contactPerson: '',
|
||||
phone: '',
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
}
|
||||
setErrors({});
|
||||
}, [account, isOpen]);
|
||||
setErrors({})
|
||||
}, [account, isOpen])
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.accountCode?.trim()) {
|
||||
newErrors.accountCode = "Hesap kodu gereklidir";
|
||||
newErrors.accountCode = 'Hesap kodu gereklidir'
|
||||
}
|
||||
|
||||
if (!formData.bankName?.trim()) {
|
||||
newErrors.bankName = "Banka adı gereklidir";
|
||||
newErrors.bankName = 'Banka adı gereklidir'
|
||||
}
|
||||
|
||||
if (!formData.branchName?.trim()) {
|
||||
newErrors.branchName = "Şube adı gereklidir";
|
||||
newErrors.branchName = 'Şube adı gereklidir'
|
||||
}
|
||||
|
||||
if (!formData.accountNumber?.trim()) {
|
||||
newErrors.accountNumber = "Hesap numarası gereklidir";
|
||||
newErrors.accountNumber = 'Hesap numarası gereklidir'
|
||||
}
|
||||
|
||||
if (!formData.iban?.trim()) {
|
||||
newErrors.iban = "IBAN gereklidir";
|
||||
newErrors.iban = 'IBAN gereklidir'
|
||||
} 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()) {
|
||||
newErrors.currency = "Para birimi gereklidir";
|
||||
newErrors.currency = 'Para birimi gereklidir'
|
||||
}
|
||||
|
||||
if (
|
||||
formData.dailyTransferLimit !== undefined &&
|
||||
formData.dailyTransferLimit < 0
|
||||
) {
|
||||
newErrors.dailyTransferLimit = "Günlük transfer limiti negatif olamaz";
|
||||
if (formData.dailyTransferLimit !== undefined && formData.dailyTransferLimit < 0) {
|
||||
newErrors.dailyTransferLimit = 'Günlük transfer limiti negatif olamaz'
|
||||
}
|
||||
|
||||
if (formData.overdraftLimit !== undefined && formData.overdraftLimit < 0) {
|
||||
newErrors.overdraftLimit = "Kredi limiti negatif olamaz";
|
||||
newErrors.overdraftLimit = 'Kredi limiti negatif olamaz'
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (validateForm()) {
|
||||
onSave(formData);
|
||||
onSave(formData)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<
|
||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
||||
>
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
const { name, value, type } = e.target;
|
||||
const parsedValue = type === "number" ? parseFloat(value) || 0 : value;
|
||||
const { name, value, type } = e.target
|
||||
const parsedValue = type === 'number' ? parseFloat(value) || 0 : value
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: parsedValue,
|
||||
}));
|
||||
}))
|
||||
|
||||
// Clear error when user starts typing
|
||||
if (errors[name]) {
|
||||
setErrors((prev) => ({
|
||||
...prev,
|
||||
[name]: "",
|
||||
}));
|
||||
[name]: '',
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, checked } = e.target;
|
||||
const { name, checked } = e.target
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: checked,
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const handleIbanChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
let value = e.target.value;
|
||||
let value = e.target.value
|
||||
|
||||
// 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
|
||||
value = value.replace(/(.{4})/g, "$1 ").trim();
|
||||
value = value.replace(/(.{4})/g, '$1 ').trim()
|
||||
|
||||
setFormData({
|
||||
...formData,
|
||||
iban: value,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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">
|
||||
<FaBuilding className="w-5 h-5 text-blue-600" />
|
||||
<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>
|
||||
</div>
|
||||
<button
|
||||
|
|
@ -182,80 +174,67 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Hesap Kodu *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Kodu *</label>
|
||||
<input
|
||||
type="text"
|
||||
name="accountCode"
|
||||
value={formData.accountCode || ""}
|
||||
value={formData.accountCode || ''}
|
||||
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 ${
|
||||
errors.accountCode ? "border-red-500" : "border-gray-300"
|
||||
errors.accountCode ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Örn: BANKA001"
|
||||
/>
|
||||
{errors.accountCode && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.accountCode}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.accountCode}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Banka Adı *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
|
||||
<input
|
||||
type="text"
|
||||
name="bankName"
|
||||
value={formData.bankName || ""}
|
||||
value={formData.bankName || ''}
|
||||
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 ${
|
||||
errors.bankName ? "border-red-500" : "border-gray-300"
|
||||
errors.bankName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Örn: İş Bankası"
|
||||
/>
|
||||
{errors.bankName && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.bankName}</p>
|
||||
)}
|
||||
{errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Şube Adı *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı *</label>
|
||||
<input
|
||||
type="text"
|
||||
name="branchName"
|
||||
value={formData.branchName || ""}
|
||||
value={formData.branchName || ''}
|
||||
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 ${
|
||||
errors.branchName ? "border-red-500" : "border-gray-300"
|
||||
errors.branchName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Örn: Levent Şubesi"
|
||||
/>
|
||||
{errors.branchName && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.branchName}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.branchName}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Hesap Türü
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Türü</label>
|
||||
<select
|
||||
name="accountType"
|
||||
value={formData.accountType || BankAccountTypeEnum.Current}
|
||||
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"
|
||||
>
|
||||
<option value={BankAccountTypeEnum.Current}>Vadesiz</option>
|
||||
<option value={BankAccountTypeEnum.Deposit}>Vadeli</option>
|
||||
<option value={BankAccountTypeEnum.Credit}>Kredi</option>
|
||||
<option value={BankAccountTypeEnum.Foreign}>Döviz</option>
|
||||
{Object.values(BankAccountTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getBankAccountTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -265,20 +244,19 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
</label>
|
||||
<select
|
||||
name="currency"
|
||||
value={formData.currency || "TRY"}
|
||||
value={formData.currency || 'TRY'}
|
||||
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 ${
|
||||
errors.currency ? "border-red-500" : "border-gray-300"
|
||||
errors.currency ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
>
|
||||
<option value="TRY">TRY - Türk Lirası</option>
|
||||
<option value="USD">USD - Amerikan Doları</option>
|
||||
<option value="EUR">EUR - Euro</option>
|
||||
<option value="GBP">GBP - İngiliz Sterlini</option>
|
||||
{mockCurrencies.map((cur) => (
|
||||
<option key={cur.value} value={cur.value}>
|
||||
{cur.value} - {cur.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.currency && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.currency}</p>
|
||||
)}
|
||||
{errors.currency && <p className="text-red-500 text-xs mt-1">{errors.currency}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -295,38 +273,32 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
name="accountNumber"
|
||||
value={formData.accountNumber || ""}
|
||||
value={formData.accountNumber || ''}
|
||||
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 ${
|
||||
errors.accountNumber ? "border-red-500" : "border-gray-300"
|
||||
errors.accountNumber ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="1234567890"
|
||||
/>
|
||||
{errors.accountNumber && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.accountNumber}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.accountNumber}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
IBAN *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">IBAN *</label>
|
||||
<input
|
||||
type="text"
|
||||
name="iban"
|
||||
value={formData.iban || ""}
|
||||
value={formData.iban || ''}
|
||||
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 ${
|
||||
errors.iban ? "border-red-500" : "border-gray-300"
|
||||
errors.iban ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="TR12 0006 4000 0011 2345 6789 01"
|
||||
maxLength={34}
|
||||
/>
|
||||
{errors.iban && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.iban}</p>
|
||||
)}
|
||||
{errors.iban && <p className="text-red-500 text-xs mt-1">{errors.iban}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -344,24 +316,20 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Kredi Limiti
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Kredi Limiti</label>
|
||||
<input
|
||||
type="number"
|
||||
name="overdraftLimit"
|
||||
value={formData.overdraftLimit || 0}
|
||||
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 ${
|
||||
errors.overdraftLimit ? "border-red-500" : "border-gray-300"
|
||||
errors.overdraftLimit ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
step="0.01"
|
||||
min="0"
|
||||
/>
|
||||
{errors.overdraftLimit && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.overdraftLimit}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.overdraftLimit}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -375,17 +343,13 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
value={formData.dailyTransferLimit || 0}
|
||||
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 ${
|
||||
errors.dailyTransferLimit
|
||||
? "border-red-500"
|
||||
: "border-gray-300"
|
||||
errors.dailyTransferLimit ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
step="0.01"
|
||||
min="0"
|
||||
/>
|
||||
{errors.dailyTransferLimit && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.dailyTransferLimit}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.dailyTransferLimit}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -404,7 +368,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
name="contactPerson"
|
||||
value={formData.contactPerson || ""}
|
||||
value={formData.contactPerson || ''}
|
||||
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"
|
||||
placeholder="Ad Soyad"
|
||||
|
|
@ -412,13 +376,11 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Telefon
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
value={formData.phone || ""}
|
||||
value={formData.phone || ''}
|
||||
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"
|
||||
placeholder="+90 212 555 1234"
|
||||
|
|
@ -434,9 +396,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
|||
onChange={handleCheckboxChange}
|
||||
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">
|
||||
Hesap aktif
|
||||
</label>
|
||||
<label className="ml-2 block text-sm text-gray-700">Hesap aktif</label>
|
||||
</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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{account ? "Güncelle" : "Kaydet"}
|
||||
{account ? 'Güncelle' : 'Kaydet'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default BankAccountForm;
|
||||
export default BankAccountForm
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaCreditCard, FaSave, FaTimes } from "react-icons/fa";
|
||||
import {
|
||||
FiCheck,
|
||||
CheckTypeEnum,
|
||||
CheckStatusEnum,
|
||||
FiCurrentAccount,
|
||||
} from "../../../types/fi";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaCreditCard, FaSave, FaTimes } from 'react-icons/fa'
|
||||
import { FiCheck, TypeEnum, CheckStatusEnum, FiCurrentAccount } from '../../../types/fi'
|
||||
import { getCheckStatusText, getTypeText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface CheckFormProps {
|
||||
check?: FiCheck;
|
||||
currentAccounts: FiCurrentAccount[];
|
||||
onSave: (
|
||||
check: Omit<FiCheck, "id" | "creationTime" | "lastModificationTime">
|
||||
) => void;
|
||||
onCancel: () => void;
|
||||
isOpen: boolean;
|
||||
check?: FiCheck
|
||||
currentAccounts: FiCurrentAccount[]
|
||||
onSave: (check: Omit<FiCheck, 'id' | 'creationTime' | 'lastModificationTime'>) => void
|
||||
onCancel: () => void
|
||||
isOpen: boolean
|
||||
}
|
||||
|
||||
const CheckForm: React.FC<CheckFormProps> = ({
|
||||
|
|
@ -25,23 +20,23 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
isOpen,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState({
|
||||
checkNumber: "",
|
||||
bankName: "",
|
||||
branchName: "",
|
||||
accountNumber: "",
|
||||
drawerName: "",
|
||||
payeeName: "",
|
||||
currentAccountId: "",
|
||||
issueDate: new Date().toISOString().split("T")[0],
|
||||
dueDate: new Date().toISOString().split("T")[0],
|
||||
checkNumber: '',
|
||||
bankName: '',
|
||||
branchName: '',
|
||||
accountNumber: '',
|
||||
drawerName: '',
|
||||
payeeName: '',
|
||||
currentAccountId: '',
|
||||
issueDate: new Date().toISOString().split('T')[0],
|
||||
dueDate: new Date().toISOString().split('T')[0],
|
||||
amount: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: CheckStatusEnum.InHand,
|
||||
type: CheckTypeEnum.Received,
|
||||
notes: "",
|
||||
});
|
||||
type: TypeEnum.Received,
|
||||
notes: '',
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||
|
||||
useEffect(() => {
|
||||
if (check) {
|
||||
|
|
@ -52,64 +47,64 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
accountNumber: check.accountNumber,
|
||||
drawerName: check.drawerName,
|
||||
payeeName: check.payeeName,
|
||||
currentAccountId: check.currentAccountId || "",
|
||||
issueDate: new Date(check.issueDate).toISOString().split("T")[0],
|
||||
dueDate: new Date(check.dueDate).toISOString().split("T")[0],
|
||||
currentAccountId: check.currentAccountId || '',
|
||||
issueDate: new Date(check.issueDate).toISOString().split('T')[0],
|
||||
dueDate: new Date(check.dueDate).toISOString().split('T')[0],
|
||||
amount: check.amount,
|
||||
currency: check.currency,
|
||||
status: check.status,
|
||||
type: check.type,
|
||||
notes: check.notes || "",
|
||||
});
|
||||
notes: check.notes || '',
|
||||
})
|
||||
} else {
|
||||
setFormData({
|
||||
checkNumber: "",
|
||||
bankName: "",
|
||||
branchName: "",
|
||||
accountNumber: "",
|
||||
drawerName: "",
|
||||
payeeName: "",
|
||||
currentAccountId: "",
|
||||
issueDate: new Date().toISOString().split("T")[0],
|
||||
dueDate: new Date().toISOString().split("T")[0],
|
||||
checkNumber: '',
|
||||
bankName: '',
|
||||
branchName: '',
|
||||
accountNumber: '',
|
||||
drawerName: '',
|
||||
payeeName: '',
|
||||
currentAccountId: '',
|
||||
issueDate: new Date().toISOString().split('T')[0],
|
||||
dueDate: new Date().toISOString().split('T')[0],
|
||||
amount: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: CheckStatusEnum.InHand,
|
||||
type: CheckTypeEnum.Received,
|
||||
notes: "",
|
||||
});
|
||||
type: TypeEnum.Received,
|
||||
notes: '',
|
||||
})
|
||||
}
|
||||
setErrors({});
|
||||
}, [check, isOpen]);
|
||||
setErrors({})
|
||||
}, [check, isOpen])
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.checkNumber.trim()) {
|
||||
newErrors.checkNumber = "Çek numarası gereklidir";
|
||||
newErrors.checkNumber = 'Çek numarası gereklidir'
|
||||
}
|
||||
if (!formData.bankName.trim()) {
|
||||
newErrors.bankName = "Banka adı gereklidir";
|
||||
newErrors.bankName = 'Banka adı gereklidir'
|
||||
}
|
||||
if (!formData.drawerName.trim()) {
|
||||
newErrors.drawerName = "Keşideci adı gereklidir";
|
||||
newErrors.drawerName = 'Keşideci adı gereklidir'
|
||||
}
|
||||
if (!formData.payeeName.trim()) {
|
||||
newErrors.payeeName = "Lehtar adı gereklidir";
|
||||
newErrors.payeeName = 'Lehtar adı gereklidir'
|
||||
}
|
||||
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)) {
|
||||
newErrors.dueDate = "Vade tarihi düzenleme tarihinden sonra olmalıdır";
|
||||
newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (validateForm()) {
|
||||
const checkData = {
|
||||
...formData,
|
||||
|
|
@ -118,22 +113,22 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
currentAccount: formData.currentAccountId
|
||||
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
|
||||
: undefined,
|
||||
};
|
||||
onSave(checkData);
|
||||
}
|
||||
onSave(checkData)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleInputChange = (
|
||||
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]) {
|
||||
setErrors((prev) => ({ ...prev, [field]: "" }));
|
||||
setErrors((prev) => ({ ...prev, [field]: '' }))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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">
|
||||
<FaCreditCard className="w-5 h-5 text-blue-600" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
{check ? "Çek Düzenle" : "Yeni Çek"}
|
||||
{check ? 'Çek Düzenle' : 'Yeni Çek'}
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
className="p-2 hover:bg-gray-100 rounded-md"
|
||||
>
|
||||
<button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
|
||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -157,102 +149,76 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
{/* Çek Bilgileri */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Çek Numarası *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Çek Numarası *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.checkNumber}
|
||||
onChange={(e) =>
|
||||
handleInputChange("checkNumber", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.checkNumber ? "border-red-500" : "border-gray-300"
|
||||
errors.checkNumber ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Çek numarasını giriniz"
|
||||
/>
|
||||
{errors.checkNumber && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.checkNumber}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.checkNumber}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Tür *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
|
||||
<select
|
||||
value={formData.type}
|
||||
onChange={(e) =>
|
||||
handleInputChange("type", e.target.value as CheckTypeEnum)
|
||||
}
|
||||
onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
|
||||
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>
|
||||
<option value={CheckTypeEnum.Issued}>Verilen Çek</option>
|
||||
{Object.values(TypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Durum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||
<select
|
||||
value={formData.status}
|
||||
onChange={(e) =>
|
||||
handleInputChange("status", e.target.value as CheckStatusEnum)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value={CheckStatusEnum.InHand}>Elde</option>
|
||||
<option value={CheckStatusEnum.Deposited}>
|
||||
Bankaya Verildi
|
||||
</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>
|
||||
{Object.values(CheckStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getCheckStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Banka Bilgileri */}
|
||||
<div className="bg-gray-50 p-3 rounded-lg">
|
||||
<h3 className="text-base font-medium text-gray-900 mb-3">
|
||||
Banka Bilgileri
|
||||
</h3>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-3">Banka Bilgileri</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Banka Adı *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.bankName}
|
||||
onChange={(e) =>
|
||||
handleInputChange("bankName", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.bankName ? "border-red-500" : "border-gray-300"
|
||||
errors.bankName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Banka adını giriniz"
|
||||
/>
|
||||
{errors.bankName && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.bankName}</p>
|
||||
)}
|
||||
{errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Şube Adı
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.branchName}
|
||||
onChange={(e) =>
|
||||
handleInputChange("branchName", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
placeholder="Şube adını giriniz"
|
||||
/>
|
||||
|
|
@ -265,9 +231,7 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={formData.accountNumber}
|
||||
onChange={(e) =>
|
||||
handleInputChange("accountNumber", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
placeholder="Hesap numarasını giriniz"
|
||||
/>
|
||||
|
|
@ -277,63 +241,45 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
|
||||
{/* Taraf Bilgileri */}
|
||||
<div className="bg-gray-50 p-3 rounded-lg">
|
||||
<h3 className="text-base font-medium text-gray-900 mb-3">
|
||||
Taraf Bilgileri
|
||||
</h3>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Keşideci *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.drawerName}
|
||||
onChange={(e) =>
|
||||
handleInputChange("drawerName", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.drawerName ? "border-red-500" : "border-gray-300"
|
||||
errors.drawerName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Keşideci adını giriniz"
|
||||
/>
|
||||
{errors.drawerName && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.drawerName}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Lehtar *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.payeeName}
|
||||
onChange={(e) =>
|
||||
handleInputChange("payeeName", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.payeeName ? "border-red-500" : "border-gray-300"
|
||||
errors.payeeName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Lehtar adını giriniz"
|
||||
/>
|
||||
{errors.payeeName && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.payeeName}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Cari Hesap
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
|
||||
<select
|
||||
value={formData.currentAccountId}
|
||||
onChange={(e) =>
|
||||
handleInputChange("currentAccountId", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Cari hesap seçiniz</option>
|
||||
|
|
@ -350,39 +296,33 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
{/* Tutar ve Tarih Bilgileri */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Tutar *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.amount}
|
||||
onChange={(e) =>
|
||||
handleInputChange("amount", parseFloat(e.target.value) || 0)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.amount ? "border-red-500" : "border-gray-300"
|
||||
errors.amount ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="0.00"
|
||||
/>
|
||||
{errors.amount && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.amount}</p>
|
||||
)}
|
||||
{errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Para Birimi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||
<select
|
||||
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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -393,37 +333,31 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
|||
<input
|
||||
type="date"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Vade Tarihi *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
|
||||
<input
|
||||
type="date"
|
||||
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 ${
|
||||
errors.dueDate ? "border-red-500" : "border-gray-300"
|
||||
errors.dueDate ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
/>
|
||||
{errors.dueDate && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>
|
||||
)}
|
||||
{errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Notlar */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Notlar
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
|
||||
<textarea
|
||||
value={formData.notes}
|
||||
onChange={(e) => handleInputChange("notes", e.target.value)}
|
||||
onChange={(e) => handleInputChange('notes', e.target.value)}
|
||||
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"
|
||||
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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{check ? "Güncelle" : "Kaydet"}
|
||||
{check ? 'Güncelle' : 'Kaydet'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CheckForm;
|
||||
export default CheckForm
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React from 'react'
|
||||
import {
|
||||
FaCreditCard,
|
||||
FaFileAlt,
|
||||
|
|
@ -7,113 +7,84 @@ import {
|
|||
FaUser,
|
||||
FaMoneyBillWave,
|
||||
FaInfoCircle,
|
||||
} from "react-icons/fa";
|
||||
} from 'react-icons/fa'
|
||||
import {
|
||||
FiCheck,
|
||||
PromissoryNote,
|
||||
CheckStatusEnum,
|
||||
NoteStatusEnum,
|
||||
CheckTypeEnum,
|
||||
NoteTypeEnum,
|
||||
} from "../../../types/fi";
|
||||
TypeEnum,
|
||||
} from '../../../types/fi'
|
||||
import {
|
||||
getCheckStatusColor,
|
||||
getCheckStatusText,
|
||||
getNoteStatusColor,
|
||||
getNoteStatusText,
|
||||
} from '@/utils/erp'
|
||||
|
||||
interface CheckNoteDetailsProps {
|
||||
item: FiCheck | PromissoryNote;
|
||||
onClose: () => void;
|
||||
isOpen: boolean;
|
||||
item: FiCheck | PromissoryNote
|
||||
onClose: () => void
|
||||
isOpen: boolean
|
||||
}
|
||||
|
||||
const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||
item,
|
||||
onClose,
|
||||
isOpen,
|
||||
}) => {
|
||||
if (!isOpen) return null;
|
||||
const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({ item, onClose, isOpen }) => {
|
||||
if (!isOpen) return null
|
||||
|
||||
const isCheck = "checkNumber" in item;
|
||||
const isCheck = 'checkNumber' in item
|
||||
const formatCurrency = (amount: number) => {
|
||||
return amount.toLocaleString("tr-TR", {
|
||||
style: "currency",
|
||||
currency: "TRY",
|
||||
return amount.toLocaleString('tr-TR', {
|
||||
style: 'currency',
|
||||
currency: 'TRY',
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
const getStatusLabel = (status: CheckStatusEnum | NoteStatusEnum) => {
|
||||
if (isCheck) {
|
||||
const statusLabels = {
|
||||
[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];
|
||||
return getCheckStatusText(status as CheckStatusEnum)
|
||||
} else {
|
||||
const statusLabels = {
|
||||
[NoteStatusEnum.InHand]: "Elde",
|
||||
[NoteStatusEnum.Collected]: "Tahsil Edildi",
|
||||
[NoteStatusEnum.Overdue]: "Vadesi Geçmiş",
|
||||
[NoteStatusEnum.Endorsed]: "Ciro Edildi",
|
||||
[NoteStatusEnum.Cancelled]: "İptal",
|
||||
};
|
||||
return statusLabels[status as NoteStatusEnum];
|
||||
return getNoteStatusText(status as NoteStatusEnum)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const getStatusColor = (status: CheckStatusEnum | NoteStatusEnum) => {
|
||||
if (isCheck) {
|
||||
const statusColors = {
|
||||
[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];
|
||||
return getCheckStatusColor(status as CheckStatusEnum)
|
||||
} else {
|
||||
const statusColors = {
|
||||
[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];
|
||||
return getNoteStatusColor(status as NoteStatusEnum)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const getTypeLabel = (type: CheckTypeEnum | NoteTypeEnum) => {
|
||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
||||
return "Alınan";
|
||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
||||
return "Verilen";
|
||||
const getTypeLabel = (type: TypeEnum) => {
|
||||
if (type === TypeEnum.Received) {
|
||||
return 'Alınan'
|
||||
} else if (type === TypeEnum.Issued) {
|
||||
return 'Verilen'
|
||||
}
|
||||
return "Bilinmeyen";
|
||||
};
|
||||
return 'Bilinmeyen'
|
||||
}
|
||||
|
||||
const getTypeColor = (type: CheckTypeEnum | NoteTypeEnum) => {
|
||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
||||
return "bg-green-100 text-green-800";
|
||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
||||
return "bg-orange-100 text-orange-800";
|
||||
const getTypeColor = (type: TypeEnum) => {
|
||||
if (type === TypeEnum.Received) {
|
||||
return 'bg-green-100 text-green-800'
|
||||
} else if (type === TypeEnum.Issued) {
|
||||
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 today = new Date();
|
||||
const due = new Date(dueDate);
|
||||
const diffTime = due.getTime() - today.getTime();
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
return diffDays;
|
||||
};
|
||||
const today = new Date()
|
||||
const due = new Date(dueDate)
|
||||
const diffTime = due.getTime() - today.getTime()
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||
return diffDays
|
||||
}
|
||||
|
||||
const daysUntilDue = getDaysUntilDue(item.dueDate);
|
||||
const isOverdue = daysUntilDue < 0;
|
||||
const isDueSoon = daysUntilDue <= 7 && daysUntilDue >= 0;
|
||||
const daysUntilDue = getDaysUntilDue(item.dueDate)
|
||||
const isOverdue = daysUntilDue < 0
|
||||
const isDueSoon = daysUntilDue <= 7 && daysUntilDue >= 0
|
||||
|
||||
return (
|
||||
<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>
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
{isCheck ? "Çek Detayları" : "Senet Detayları"}
|
||||
{isCheck ? 'Çek Detayları' : 'Senet Detayları'}
|
||||
</h2>
|
||||
<p className="text-sm text-gray-600">
|
||||
{isCheck
|
||||
? (item as FiCheck).checkNumber
|
||||
: (item as PromissoryNote).noteNumber}
|
||||
{isCheck ? (item as FiCheck).checkNumber : (item as PromissoryNote).noteNumber}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="p-2 hover:bg-gray-100 rounded-md"
|
||||
>
|
||||
<button onClick={onClose} className="p-2 hover:bg-gray-100 rounded-md">
|
||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -149,15 +115,13 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
<div className="flex items-center gap-3">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor(
|
||||
item.status
|
||||
item.status,
|
||||
)}`}
|
||||
>
|
||||
{getStatusLabel(item.status)}
|
||||
</span>
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getTypeColor(
|
||||
item.type
|
||||
)}`}
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getTypeColor(item.type)}`}
|
||||
>
|
||||
{getTypeLabel(item.type)}
|
||||
</span>
|
||||
|
|
@ -183,13 +147,9 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
</h3>
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">
|
||||
{isCheck ? "Çek No:" : "Senet No:"}
|
||||
</span>
|
||||
<span className="text-gray-600">{isCheck ? 'Çek No:' : 'Senet No:'}</span>
|
||||
<span className="font-medium">
|
||||
{isCheck
|
||||
? (item as FiCheck).checkNumber
|
||||
: (item as PromissoryNote).noteNumber}
|
||||
{isCheck ? (item as FiCheck).checkNumber : (item as PromissoryNote).noteNumber}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
|
|
@ -205,9 +165,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
{!isCheck && (item as PromissoryNote).location && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Konum:</span>
|
||||
<span className="font-medium">
|
||||
{(item as PromissoryNote).location}
|
||||
</span>
|
||||
<span className="font-medium">{(item as PromissoryNote).location}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -223,35 +181,29 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Düzenleme Tarihi:</span>
|
||||
<span className="font-medium">
|
||||
{new Date(item.issueDate).toLocaleDateString("tr-TR")}
|
||||
{new Date(item.issueDate).toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Vade Tarihi:</span>
|
||||
<span
|
||||
className={`font-medium ${
|
||||
isOverdue
|
||||
? "text-red-600"
|
||||
: isDueSoon
|
||||
? "text-orange-600"
|
||||
: "text-gray-900"
|
||||
isOverdue ? '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>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Oluşturma Tarihi:</span>
|
||||
<span className="font-medium">
|
||||
{new Date(item.creationTime).toLocaleDateString("tr-TR")}
|
||||
{new Date(item.creationTime).toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Son Güncelleme:</span>
|
||||
<span className="font-medium">
|
||||
{new Date(item.lastModificationTime).toLocaleDateString(
|
||||
"tr-TR"
|
||||
)}
|
||||
{new Date(item.lastModificationTime).toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -267,24 +219,16 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm">
|
||||
<div>
|
||||
<span className="text-gray-600 block text-sm">
|
||||
Banka Adı:
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{(item as FiCheck).bankName}
|
||||
</span>
|
||||
<span className="text-gray-600 block text-sm">Banka Adı:</span>
|
||||
<span className="font-medium">{(item as FiCheck).bankName}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-gray-600 block text-sm">Şube Adı:</span>
|
||||
<span className="font-medium">
|
||||
{(item as FiCheck).branchName}
|
||||
</span>
|
||||
<span className="font-medium">{(item as FiCheck).branchName}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-gray-600 block text-sm">Hesap No:</span>
|
||||
<span className="font-medium">
|
||||
{(item as FiCheck).accountNumber}
|
||||
</span>
|
||||
<span className="font-medium">{(item as FiCheck).accountNumber}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -308,12 +252,9 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
</div>
|
||||
{item.currentAccount && (
|
||||
<div className="mt-3 p-2 bg-blue-50 rounded-lg text-sm">
|
||||
<span className="text-gray-600 block text-sm">
|
||||
Bağlı Cari Hesap:
|
||||
</span>
|
||||
<span className="text-gray-600 block text-sm">Bağlı Cari Hesap:</span>
|
||||
<span className="font-medium text-blue-600">
|
||||
{item.currentAccount.accountCode} -{" "}
|
||||
{item.currentAccount.accountCode}
|
||||
{item.currentAccount.accountCode} - {item.currentAccount.accountCode}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -330,9 +271,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
<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="font-medium">
|
||||
{new Date((item as FiCheck).bankingDate!).toLocaleDateString(
|
||||
"tr-TR"
|
||||
)}
|
||||
{new Date((item as FiCheck).bankingDate!).toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -340,35 +279,27 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
<div className="flex justify-between items-center p-3 bg-green-50 rounded-lg">
|
||||
<span className="text-gray-700">Tahsil Tarihi:</span>
|
||||
<span className="font-medium">
|
||||
{new Date(item.collectionDate).toLocaleDateString("tr-TR")}
|
||||
{new Date(item.collectionDate).toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{item.endorsedTo && (
|
||||
<div className="flex justify-between items-center p-3 bg-purple-50 rounded-lg">
|
||||
<span className="text-gray-700">
|
||||
Ciro Edildiği Kişi/Kuruluş:
|
||||
</span>
|
||||
<span className="text-gray-700">Ciro Edildiği Kişi/Kuruluş:</span>
|
||||
<span className="font-medium">{item.endorsedTo}</span>
|
||||
</div>
|
||||
)}
|
||||
{(!isCheck || !(item as FiCheck).bankingDate) &&
|
||||
!item.collectionDate &&
|
||||
!item.endorsedTo && (
|
||||
<p className="text-gray-500 italic">Henüz işlem yapılmamış</p>
|
||||
)}
|
||||
!item.endorsedTo && <p className="text-gray-500 italic">Henüz işlem yapılmamış</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Notlar */}
|
||||
{item.notes && (
|
||||
<div className="bg-gray-50 p-3 rounded-lg">
|
||||
<h3 className="text-base font-medium text-gray-900 mb-2">
|
||||
Notlar
|
||||
</h3>
|
||||
<p className="text-sm text-gray-700 whitespace-pre-wrap">
|
||||
{item.notes}
|
||||
</p>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-2">Notlar</h3>
|
||||
<p className="text-sm text-gray-700 whitespace-pre-wrap">{item.notes}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -384,7 +315,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CheckNoteDetails;
|
||||
export default CheckNoteDetails
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ import {
|
|||
PromissoryNote,
|
||||
CheckStatusEnum,
|
||||
NoteStatusEnum,
|
||||
CheckTypeEnum,
|
||||
NoteTypeEnum,
|
||||
TypeEnum,
|
||||
FiCurrentAccount,
|
||||
} from '../../../types/fi'
|
||||
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||
|
|
@ -71,7 +70,7 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
|||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [selectedCheckStatus, setSelectedCheckStatus] = useState<CheckStatusEnum | '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')
|
||||
|
||||
// Dialog states
|
||||
|
|
@ -242,19 +241,19 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
|||
}
|
||||
})
|
||||
|
||||
const getTypeLabel = (type: CheckTypeEnum | NoteTypeEnum) => {
|
||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
||||
const getTypeLabel = (type: TypeEnum) => {
|
||||
if (type === TypeEnum.Received) {
|
||||
return 'Alınan'
|
||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
||||
} else if (type === TypeEnum.Issued) {
|
||||
return 'Verilen'
|
||||
}
|
||||
return 'Bilinmeyen'
|
||||
}
|
||||
|
||||
const getTypeColor = (type: CheckTypeEnum | NoteTypeEnum) => {
|
||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
||||
const getTypeColor = (type: TypeEnum) => {
|
||||
if (type === TypeEnum.Received) {
|
||||
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-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 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)
|
||||
|
||||
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)
|
||||
|
||||
// Due items
|
||||
|
|
@ -756,9 +755,7 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={selectedType}
|
||||
onChange={(e) =>
|
||||
setSelectedType(e.target.value as CheckTypeEnum | NoteTypeEnum | 'all')
|
||||
}
|
||||
onChange={(e) => setSelectedType(e.target.value as TypeEnum | '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"
|
||||
>
|
||||
<option value="all">Tüm Türler</option>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,15 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
FaTimes,
|
||||
FaUser,
|
||||
FaBuilding,
|
||||
FaCreditCard,
|
||||
FaPhoneAlt,
|
||||
} from "react-icons/fa";
|
||||
import {
|
||||
FiCurrentAccount,
|
||||
AccountTypeEnum,
|
||||
RiskGroupEnum,
|
||||
} from "../../../types/fi";
|
||||
import { mockBusinessParties } from "../../../mocks/mockBusinessParties";
|
||||
import { getAccountTypeText, getRiskGroupText } from "../../../utils/erp";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaTimes, FaUser, FaBuilding, FaCreditCard, FaPhoneAlt } from 'react-icons/fa'
|
||||
import { FiCurrentAccount, AccountTypeEnum, RiskGroupEnum } from '../../../types/fi'
|
||||
import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
||||
import { getAccountTypeText, getRiskGroupText } from '../../../utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface CurrentAccountFormProps {
|
||||
account?: FiCurrentAccount;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (account: Partial<FiCurrentAccount>) => void;
|
||||
account?: FiCurrentAccount
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (account: Partial<FiCurrentAccount>) => void
|
||||
}
|
||||
|
||||
const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||
|
|
@ -29,26 +20,26 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
}) => {
|
||||
const [formData, setFormData] = useState<
|
||||
Partial<FiCurrentAccount> & {
|
||||
id?: string;
|
||||
id?: string
|
||||
}
|
||||
>({
|
||||
accountCode: "",
|
||||
businessPartyId: "",
|
||||
accountCode: '',
|
||||
businessPartyId: '',
|
||||
type: AccountTypeEnum.Customer,
|
||||
contactPerson: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
address: "",
|
||||
taxNumber: "",
|
||||
taxOffice: "",
|
||||
contactPerson: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
address: '',
|
||||
taxNumber: '',
|
||||
taxOffice: '',
|
||||
creditLimit: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
riskGroup: RiskGroupEnum.Low,
|
||||
paymentTerm: 30,
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||
|
||||
useEffect(() => {
|
||||
if (account) {
|
||||
|
|
@ -56,100 +47,95 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
...account,
|
||||
creditLimit: account.creditLimit || 0,
|
||||
paymentTerm: account.paymentTerm || 30,
|
||||
});
|
||||
})
|
||||
} else {
|
||||
setFormData({
|
||||
accountCode: "",
|
||||
businessPartyId: "",
|
||||
accountCode: '',
|
||||
businessPartyId: '',
|
||||
type: AccountTypeEnum.Customer,
|
||||
contactPerson: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
address: "",
|
||||
taxNumber: "",
|
||||
taxOffice: "",
|
||||
contactPerson: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
address: '',
|
||||
taxNumber: '',
|
||||
taxOffice: '',
|
||||
creditLimit: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
riskGroup: RiskGroupEnum.Low,
|
||||
paymentTerm: 30,
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
}
|
||||
setErrors({});
|
||||
}, [account, isOpen]);
|
||||
setErrors({})
|
||||
}, [account, isOpen])
|
||||
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<
|
||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
||||
>
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
const { name, value, type } = e.target;
|
||||
let parsedValue: string | number | boolean = value;
|
||||
const { name, value, type } = e.target
|
||||
let parsedValue: string | number | boolean = value
|
||||
|
||||
if (type === "number") {
|
||||
parsedValue = value === "" ? 0 : parseFloat(value);
|
||||
} else if (type === "checkbox") {
|
||||
parsedValue = (e.target as HTMLInputElement).checked;
|
||||
if (type === 'number') {
|
||||
parsedValue = value === '' ? 0 : parseFloat(value)
|
||||
} else if (type === 'checkbox') {
|
||||
parsedValue = (e.target as HTMLInputElement).checked
|
||||
}
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: parsedValue,
|
||||
}));
|
||||
}))
|
||||
|
||||
// Clear error when user starts typing
|
||||
if (errors[name]) {
|
||||
setErrors((prev) => ({
|
||||
...prev,
|
||||
[name]: "",
|
||||
}));
|
||||
[name]: '',
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.accountCode?.trim()) {
|
||||
newErrors.accountCode = "Hesap kodu zorunludur";
|
||||
newErrors.accountCode = 'Hesap kodu zorunludur'
|
||||
}
|
||||
if (!formData.businessPartyId?.trim()) {
|
||||
newErrors.businessPartyId = "Ünvan zorunludur";
|
||||
newErrors.businessPartyId = 'Ünvan zorunludur'
|
||||
}
|
||||
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) {
|
||||
newErrors.creditLimit = "Kredi limiti negatif olamaz";
|
||||
newErrors.creditLimit = 'Kredi limiti negatif olamaz'
|
||||
}
|
||||
if (formData.paymentTerm && formData.paymentTerm < 0) {
|
||||
newErrors.paymentTerm = "Ödeme vadesi negatif olamaz";
|
||||
newErrors.paymentTerm = 'Ödeme vadesi negatif olamaz'
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (validateForm()) {
|
||||
onSave(formData);
|
||||
onClose();
|
||||
onSave(formData)
|
||||
onClose()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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="flex items-center justify-between p-4 border-b">
|
||||
<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>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -164,34 +150,28 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Hesap Kodu *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Kodu *</label>
|
||||
<input
|
||||
type="text"
|
||||
name="accountCode"
|
||||
value={formData.accountCode || ""}
|
||||
value={formData.accountCode || ''}
|
||||
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 ${
|
||||
errors.accountCode ? "border-red-500" : "border-gray-300"
|
||||
errors.accountCode ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="CA001"
|
||||
/>
|
||||
{errors.accountCode && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.accountCode}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.accountCode}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Ünvan *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Ünvan *</label>
|
||||
|
||||
<select
|
||||
name="businessPartyId"
|
||||
value={formData.businessPartyId || ""}
|
||||
value={formData.businessPartyId || ''}
|
||||
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"
|
||||
required
|
||||
|
|
@ -203,15 +183,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.title && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.title}</p>
|
||||
)}
|
||||
{errors.title && <p className="text-red-500 text-xs mt-1">{errors.title}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Hesap Türü
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Türü</label>
|
||||
<select
|
||||
name="type"
|
||||
value={formData.type}
|
||||
|
|
@ -227,13 +203,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Yetkili Kişi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Yetkili Kişi</label>
|
||||
<input
|
||||
type="text"
|
||||
name="contactPerson"
|
||||
value={formData.contactPerson || ""}
|
||||
value={formData.contactPerson || ''}
|
||||
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"
|
||||
placeholder="Yetkili kişi adı"
|
||||
|
|
@ -249,13 +223,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Telefon
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
|
||||
<input
|
||||
type="text"
|
||||
name="phone"
|
||||
value={formData.phone || ""}
|
||||
value={formData.phone || ''}
|
||||
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"
|
||||
placeholder="+90 212 555 1234"
|
||||
|
|
@ -263,31 +235,25 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
E-posta
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={formData.email || ""}
|
||||
value={formData.email || ''}
|
||||
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 ${
|
||||
errors.email ? "border-red-500" : "border-gray-300"
|
||||
errors.email ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="info@company.com"
|
||||
/>
|
||||
{errors.email && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.email}</p>
|
||||
)}
|
||||
{errors.email && <p className="text-red-500 text-xs mt-1">{errors.email}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Adres
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Adres</label>
|
||||
<textarea
|
||||
name="address"
|
||||
value={formData.address || ""}
|
||||
value={formData.address || ''}
|
||||
onChange={handleInputChange}
|
||||
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"
|
||||
|
|
@ -303,7 +269,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
name="taxNumber"
|
||||
value={formData.taxNumber || ""}
|
||||
value={formData.taxNumber || ''}
|
||||
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"
|
||||
placeholder="1234567890"
|
||||
|
|
@ -317,7 +283,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
name="taxOffice"
|
||||
value={formData.taxOffice || ""}
|
||||
value={formData.taxOffice || ''}
|
||||
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"
|
||||
placeholder="Beylikdüzü V.D."
|
||||
|
|
@ -346,14 +312,12 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
min="0"
|
||||
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 ${
|
||||
errors.creditLimit ? "border-red-500" : "border-gray-300"
|
||||
errors.creditLimit ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="0.00"
|
||||
/>
|
||||
{errors.creditLimit && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.creditLimit}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.creditLimit}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -367,19 +331,18 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value="TRY">TRY - Türk Lirası</option>
|
||||
<option value="USD">USD - Amerikan Doları</option>
|
||||
<option value="EUR">EUR - Euro</option>
|
||||
<option value="GBP">GBP - İngiliz Sterlini</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Risk Grubu
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Risk Grubu</label>
|
||||
<select
|
||||
name="riskGroup"
|
||||
value={formData.riskGroup}
|
||||
|
|
@ -405,14 +368,12 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
onChange={handleInputChange}
|
||||
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 ${
|
||||
errors.paymentTerm ? "border-red-500" : "border-gray-300"
|
||||
errors.paymentTerm ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="30"
|
||||
/>
|
||||
{errors.paymentTerm && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.paymentTerm}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.paymentTerm}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -433,9 +394,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
onChange={handleInputChange}
|
||||
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">
|
||||
Aktif hesap
|
||||
</label>
|
||||
<label className="ml-2 block text-sm text-gray-700">Aktif hesap</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -453,13 +412,13 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
|||
type="submit"
|
||||
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>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CurrentAccountForm;
|
||||
export default CurrentAccountForm
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaTimes, FaFileInvoice, FaMoneyBill } from "react-icons/fa";
|
||||
import {
|
||||
FiCurrentAccountMovement,
|
||||
FiDocumentTypeEnum,
|
||||
FiCurrentAccount,
|
||||
} from "../../../types/fi";
|
||||
import { getFiDocumentTypeText } from "../../../utils/erp";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaTimes, FaFileInvoice, FaMoneyBill } from 'react-icons/fa'
|
||||
import { FiCurrentAccountMovement, FiDocumentTypeEnum, FiCurrentAccount } from '../../../types/fi'
|
||||
import { getFiDocumentTypeText } from '../../../utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface CurrentAccountMovementFormProps {
|
||||
movement?: FiCurrentAccountMovement;
|
||||
accounts: FiCurrentAccount[];
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (movement: Partial<FiCurrentAccountMovement>) => void;
|
||||
movement?: FiCurrentAccountMovement
|
||||
accounts: FiCurrentAccount[]
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (movement: Partial<FiCurrentAccountMovement>) => void
|
||||
}
|
||||
|
||||
const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||
|
|
@ -24,22 +21,22 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
}) => {
|
||||
const [formData, setFormData] = useState<
|
||||
Partial<FiCurrentAccountMovement> & {
|
||||
id?: string;
|
||||
id?: string
|
||||
}
|
||||
>({
|
||||
accountId: "",
|
||||
accountId: '',
|
||||
transactionDate: new Date(),
|
||||
description: "",
|
||||
referenceNumber: "",
|
||||
description: '',
|
||||
referenceNumber: '',
|
||||
documentType: FiDocumentTypeEnum.Invoice,
|
||||
documentNumber: "",
|
||||
documentNumber: '',
|
||||
debitAmount: 0,
|
||||
creditAmount: 0,
|
||||
balance: 0,
|
||||
currency: "TRY",
|
||||
});
|
||||
currency: 'TRY',
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||
|
||||
useEffect(() => {
|
||||
if (movement) {
|
||||
|
|
@ -48,111 +45,100 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
debitAmount: movement.debitAmount || 0,
|
||||
creditAmount: movement.creditAmount || 0,
|
||||
balance: movement.balance || 0,
|
||||
});
|
||||
})
|
||||
} else {
|
||||
setFormData({
|
||||
accountId: "",
|
||||
accountId: '',
|
||||
transactionDate: new Date(),
|
||||
description: "",
|
||||
referenceNumber: "",
|
||||
description: '',
|
||||
referenceNumber: '',
|
||||
documentType: FiDocumentTypeEnum.Invoice,
|
||||
documentNumber: "",
|
||||
documentNumber: '',
|
||||
debitAmount: 0,
|
||||
creditAmount: 0,
|
||||
balance: 0,
|
||||
currency: "TRY",
|
||||
});
|
||||
currency: 'TRY',
|
||||
})
|
||||
}
|
||||
setErrors({});
|
||||
}, [movement, isOpen]);
|
||||
setErrors({})
|
||||
}, [movement, isOpen])
|
||||
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<
|
||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
||||
>
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
const { name, value, type } = e.target;
|
||||
let parsedValue: string | number | Date = value;
|
||||
const { name, value, type } = e.target
|
||||
let parsedValue: string | number | Date = value
|
||||
|
||||
if (type === "number") {
|
||||
parsedValue = value === "" ? 0 : parseFloat(value);
|
||||
} else if (type === "date") {
|
||||
parsedValue = new Date(value);
|
||||
if (type === 'number') {
|
||||
parsedValue = value === '' ? 0 : parseFloat(value)
|
||||
} else if (type === 'date') {
|
||||
parsedValue = new Date(value)
|
||||
}
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: parsedValue,
|
||||
}));
|
||||
}))
|
||||
|
||||
// Clear error when user starts typing
|
||||
if (errors[name]) {
|
||||
setErrors((prev) => ({
|
||||
...prev,
|
||||
[name]: "",
|
||||
}));
|
||||
[name]: '',
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.accountId) {
|
||||
newErrors.accountId = "Cari hesap seçimi zorunludur";
|
||||
newErrors.accountId = 'Cari hesap seçimi zorunludur'
|
||||
}
|
||||
if (!formData.description?.trim()) {
|
||||
newErrors.description = "Açıklama zorunludur";
|
||||
newErrors.description = 'Açıklama zorunludur'
|
||||
}
|
||||
if (!formData.transactionDate) {
|
||||
newErrors.transactionDate = "İşlem tarihi zorunludur";
|
||||
newErrors.transactionDate = 'İşlem tarihi zorunludur'
|
||||
}
|
||||
if (
|
||||
(formData.debitAmount || 0) === 0 &&
|
||||
(formData.creditAmount || 0) === 0
|
||||
) {
|
||||
newErrors.amount = "Borç veya alacak tutarından biri girilmelidir";
|
||||
if ((formData.debitAmount || 0) === 0 && (formData.creditAmount || 0) === 0) {
|
||||
newErrors.amount = 'Borç veya alacak tutarından biri girilmelidir'
|
||||
}
|
||||
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);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (validateForm()) {
|
||||
// Calculate balance based on debit/credit amounts
|
||||
const balance =
|
||||
(formData.debitAmount || 0) - (formData.creditAmount || 0);
|
||||
const balance = (formData.debitAmount || 0) - (formData.creditAmount || 0)
|
||||
|
||||
const movementData = {
|
||||
...formData,
|
||||
balance,
|
||||
creationTime: movement?.creationTime || new Date(),
|
||||
};
|
||||
}
|
||||
|
||||
onSave(movementData);
|
||||
onClose();
|
||||
onSave(movementData)
|
||||
onClose()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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="flex items-center justify-between p-4 border-b">
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
{movement
|
||||
? "Cari Hesap Hareketi Düzenle"
|
||||
: "Yeni Cari Hesap Hareketi"}
|
||||
{movement ? 'Cari Hesap Hareketi Düzenle' : 'Yeni Cari Hesap Hareketi'}
|
||||
</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -167,15 +153,13 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Cari Hesap *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap *</label>
|
||||
<select
|
||||
name="accountId"
|
||||
value={formData.accountId || ""}
|
||||
value={formData.accountId || ''}
|
||||
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 ${
|
||||
errors.accountId ? "border-red-500" : "border-gray-300"
|
||||
errors.accountId ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
>
|
||||
<option value="">Cari hesap seçiniz</option>
|
||||
|
|
@ -186,9 +170,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
))}
|
||||
</select>
|
||||
{errors.accountId && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.accountId}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.accountId}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -201,29 +183,21 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
name="transactionDate"
|
||||
value={
|
||||
formData.transactionDate
|
||||
? new Date(formData.transactionDate)
|
||||
.toISOString()
|
||||
.split("T")[0]
|
||||
: ""
|
||||
? new Date(formData.transactionDate).toISOString().split('T')[0]
|
||||
: ''
|
||||
}
|
||||
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 ${
|
||||
errors.transactionDate
|
||||
? "border-red-500"
|
||||
: "border-gray-300"
|
||||
errors.transactionDate ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
/>
|
||||
{errors.transactionDate && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.transactionDate}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.transactionDate}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Belge Türü
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Belge Türü</label>
|
||||
<select
|
||||
name="documentType"
|
||||
value={formData.documentType}
|
||||
|
|
@ -246,7 +220,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
name="referenceNumber"
|
||||
value={formData.referenceNumber || ""}
|
||||
value={formData.referenceNumber || ''}
|
||||
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"
|
||||
placeholder="REF001"
|
||||
|
|
@ -254,13 +228,11 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Belge No
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Belge No</label>
|
||||
<input
|
||||
type="text"
|
||||
name="documentNumber"
|
||||
value={formData.documentNumber || ""}
|
||||
value={formData.documentNumber || ''}
|
||||
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"
|
||||
placeholder="DOC001"
|
||||
|
|
@ -277,9 +249,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Borç Tutarı
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Borç Tutarı</label>
|
||||
<input
|
||||
type="number"
|
||||
name="debitAmount"
|
||||
|
|
@ -309,19 +279,18 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Para Birimi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||
<select
|
||||
name="currency"
|
||||
value={formData.currency}
|
||||
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"
|
||||
>
|
||||
<option value="TRY">TRY - Türk Lirası</option>
|
||||
<option value="USD">USD - Amerikan Doları</option>
|
||||
<option value="EUR">EUR - Euro</option>
|
||||
<option value="GBP">GBP - İngiliz Sterlini</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -333,37 +302,34 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
|
||||
<div className="p-2 bg-blue-50 border border-blue-200 rounded-md">
|
||||
<p className="text-blue-800 text-sm">
|
||||
<strong>Hesaplanan Bakiye:</strong>{" "}
|
||||
{(
|
||||
(formData.debitAmount || 0) - (formData.creditAmount || 0)
|
||||
).toLocaleString("tr-TR", {
|
||||
style: "currency",
|
||||
currency: formData.currency || "TRY",
|
||||
minimumFractionDigits: 2,
|
||||
})}
|
||||
<strong>Hesaplanan Bakiye:</strong>{' '}
|
||||
{((formData.debitAmount || 0) - (formData.creditAmount || 0)).toLocaleString(
|
||||
'tr-TR',
|
||||
{
|
||||
style: 'currency',
|
||||
currency: formData.currency || 'TRY',
|
||||
minimumFractionDigits: 2,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Açıklama */}
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Açıklama *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama *</label>
|
||||
<textarea
|
||||
name="description"
|
||||
value={formData.description || ""}
|
||||
value={formData.description || ''}
|
||||
onChange={handleInputChange}
|
||||
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 ${
|
||||
errors.description ? "border-red-500" : "border-gray-300"
|
||||
errors.description ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Hareket açıklaması"
|
||||
/>
|
||||
{errors.description && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.description}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.description}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -381,13 +347,13 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
|||
type="submit"
|
||||
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>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CurrentAccountMovementForm;
|
||||
export default CurrentAccountMovementForm
|
||||
|
|
|
|||
|
|
@ -1,31 +1,27 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from "react-icons/fa";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from 'react-icons/fa'
|
||||
import {
|
||||
FiInvoice,
|
||||
FiInvoiceItem,
|
||||
InvoiceTypeEnum,
|
||||
InvoiceStatusEnum,
|
||||
PaymentStatusEnum,
|
||||
} from "../../../types/fi";
|
||||
import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts";
|
||||
} from '../../../types/fi'
|
||||
import { mockCurrentAccounts } from '../../../mocks/mockCurrentAccounts'
|
||||
import { getInvoiceTypeText } from '@/utils/erp'
|
||||
|
||||
interface InvoiceFormProps {
|
||||
invoice?: FiInvoice;
|
||||
onSave: (invoice: Partial<FiInvoice>) => void;
|
||||
onCancel: () => void;
|
||||
isVisible: boolean;
|
||||
invoice?: FiInvoice
|
||||
onSave: (invoice: Partial<FiInvoice>) => void
|
||||
onCancel: () => void
|
||||
isVisible: boolean
|
||||
}
|
||||
|
||||
const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||
invoice,
|
||||
onSave,
|
||||
onCancel,
|
||||
isVisible,
|
||||
}) => {
|
||||
const InvoiceForm: React.FC<InvoiceFormProps> = ({ invoice, onSave, onCancel, isVisible }) => {
|
||||
const [formData, setFormData] = useState<Partial<FiInvoice>>({
|
||||
invoiceNumber: "",
|
||||
invoiceNumber: '',
|
||||
invoiceType: InvoiceTypeEnum.Sales,
|
||||
currentAccountId: "",
|
||||
currentAccountId: '',
|
||||
invoiceDate: new Date(),
|
||||
dueDate: new Date(),
|
||||
deliveryDate: new Date(),
|
||||
|
|
@ -35,22 +31,22 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
totalAmount: 0,
|
||||
paidAmount: 0,
|
||||
remainingAmount: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: InvoiceStatusEnum.Draft,
|
||||
paymentStatus: PaymentStatusEnum.Unpaid,
|
||||
items: [],
|
||||
waybillNumber: "",
|
||||
notes: "",
|
||||
});
|
||||
waybillNumber: '',
|
||||
notes: '',
|
||||
})
|
||||
|
||||
const [newItem, setNewItem] = useState<Partial<FiInvoiceItem>>({
|
||||
description: "",
|
||||
description: '',
|
||||
quantity: 1,
|
||||
unitPrice: 0,
|
||||
taxRate: 18,
|
||||
discountRate: 0,
|
||||
unit: "Adet",
|
||||
});
|
||||
unit: 'Adet',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (invoice) {
|
||||
|
|
@ -58,18 +54,17 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
...invoice,
|
||||
invoiceDate: new Date(invoice.invoiceDate),
|
||||
dueDate: new Date(invoice.dueDate),
|
||||
deliveryDate: invoice.deliveryDate
|
||||
? new Date(invoice.deliveryDate)
|
||||
: new Date(),
|
||||
});
|
||||
deliveryDate: invoice.deliveryDate ? new Date(invoice.deliveryDate) : new Date(),
|
||||
})
|
||||
} else {
|
||||
// Generate new invoice number
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
||||
const invoiceNumber = `FT${year}${month}${String(
|
||||
Math.floor(Math.random() * 10000)
|
||||
).padStart(4, "0")}`;
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const invoiceNumber = `FT${year}${month}${String(Math.floor(Math.random() * 10000)).padStart(
|
||||
4,
|
||||
'0',
|
||||
)}`
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
|
|
@ -77,58 +72,50 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
invoiceDate: now,
|
||||
dueDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), // 30 days
|
||||
deliveryDate: now,
|
||||
}));
|
||||
}))
|
||||
}
|
||||
}, [invoice]);
|
||||
}, [invoice])
|
||||
|
||||
const calculateItemTotal = (item: Partial<FiInvoiceItem>) => {
|
||||
const subtotal = (item.quantity || 0) * (item.unitPrice || 0);
|
||||
const discountAmount = subtotal * ((item.discountRate || 0) / 100);
|
||||
const taxableAmount = subtotal - discountAmount;
|
||||
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100);
|
||||
return taxableAmount + taxAmount;
|
||||
};
|
||||
const subtotal = (item.quantity || 0) * (item.unitPrice || 0)
|
||||
const discountAmount = subtotal * ((item.discountRate || 0) / 100)
|
||||
const taxableAmount = subtotal - discountAmount
|
||||
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100)
|
||||
return taxableAmount + taxAmount
|
||||
}
|
||||
|
||||
const calculateInvoiceTotals = (items: FiInvoiceItem[]) => {
|
||||
const subtotal = items.reduce(
|
||||
(sum, item) => sum + item.quantity * item.unitPrice,
|
||||
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);
|
||||
const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 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 {
|
||||
subtotal,
|
||||
discountAmount,
|
||||
taxAmount,
|
||||
totalAmount,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const handleAddItem = () => {
|
||||
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
|
||||
alert("Lütfen ürün bilgilerini doldurun");
|
||||
return;
|
||||
alert('Lütfen ürün bilgilerini doldurun')
|
||||
return
|
||||
}
|
||||
|
||||
const item: FiInvoiceItem = {
|
||||
id: Date.now().toString(),
|
||||
invoiceId: formData.id || "",
|
||||
invoiceId: formData.id || '',
|
||||
description: newItem.description!,
|
||||
quantity: newItem.quantity!,
|
||||
unitPrice: newItem.unitPrice!,
|
||||
unit: newItem.unit || "Adet",
|
||||
unit: newItem.unit || 'Adet',
|
||||
taxRate: newItem.taxRate || 18,
|
||||
discountRate: newItem.discountRate || 0,
|
||||
lineTotal: calculateItemTotal(newItem),
|
||||
discountAmount:
|
||||
(newItem.quantity || 0) *
|
||||
(newItem.unitPrice || 0) *
|
||||
((newItem.discountRate || 0) / 100),
|
||||
(newItem.quantity || 0) * (newItem.unitPrice || 0) * ((newItem.discountRate || 0) / 100),
|
||||
taxAmount:
|
||||
((newItem.quantity || 0) * (newItem.unitPrice || 0) -
|
||||
(newItem.quantity || 0) *
|
||||
|
|
@ -136,50 +123,49 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
((newItem.discountRate || 0) / 100)) *
|
||||
((newItem.taxRate || 0) / 100),
|
||||
netAmount: calculateItemTotal(newItem),
|
||||
};
|
||||
}
|
||||
|
||||
const updatedItems = [...(formData.items || []), item];
|
||||
const totals = calculateInvoiceTotals(updatedItems);
|
||||
const updatedItems = [...(formData.items || []), item]
|
||||
const totals = calculateInvoiceTotals(updatedItems)
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
items: updatedItems,
|
||||
...totals,
|
||||
remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
|
||||
}));
|
||||
}))
|
||||
|
||||
setNewItem({
|
||||
description: "",
|
||||
description: '',
|
||||
quantity: 1,
|
||||
unitPrice: 0,
|
||||
taxRate: 18,
|
||||
discountRate: 0,
|
||||
unit: "Adet",
|
||||
});
|
||||
};
|
||||
unit: 'Adet',
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemoveItem = (itemId: string) => {
|
||||
const updatedItems =
|
||||
formData.items?.filter((item) => item.id !== itemId) || [];
|
||||
const totals = calculateInvoiceTotals(updatedItems);
|
||||
const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []
|
||||
const totals = calculateInvoiceTotals(updatedItems)
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
items: updatedItems,
|
||||
...totals,
|
||||
remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (!formData.currentAccountId) {
|
||||
alert("Lütfen cari hesap seçin");
|
||||
return;
|
||||
alert('Lütfen cari hesap seçin')
|
||||
return
|
||||
}
|
||||
if (!formData.items?.length) {
|
||||
alert("Lütfen en az bir ürün ekleyin");
|
||||
return;
|
||||
alert('Lütfen en az bir ürün ekleyin')
|
||||
return
|
||||
}
|
||||
|
||||
onSave({
|
||||
|
|
@ -187,18 +173,18 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
id: invoice?.id || Date.now().toString(),
|
||||
creationTime: invoice?.creationTime || new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
const formatCurrency = (amount: number) => {
|
||||
return amount.toLocaleString("tr-TR", {
|
||||
style: "currency",
|
||||
currency: "TRY",
|
||||
return amount.toLocaleString('tr-TR', {
|
||||
style: 'currency',
|
||||
currency: 'TRY',
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
if (!isVisible) return null;
|
||||
if (!isVisible) return null
|
||||
|
||||
return (
|
||||
<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">
|
||||
<FaFileAlt className="w-5 h-5 text-blue-600" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
{invoice ? "Fatura Düzenle" : "Yeni Fatura"}
|
||||
{invoice ? 'Fatura Düzenle' : 'Yeni Fatura'}
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
|
|
@ -224,24 +210,18 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
{/* Basic Information */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Fatura No
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Fatura No</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.invoiceNumber}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, invoiceNumber: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Fatura Türü
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Fatura Türü</label>
|
||||
<select
|
||||
value={formData.invoiceType}
|
||||
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"
|
||||
>
|
||||
<option value={InvoiceTypeEnum.Sales}>Satış</option>
|
||||
<option value={InvoiceTypeEnum.Purchase}>Alış</option>
|
||||
<option value={InvoiceTypeEnum.Return}>İade</option>
|
||||
<option value={InvoiceTypeEnum.Proforma}>Proforma</option>
|
||||
{Object.values(InvoiceTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getInvoiceTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
İrsaliye No
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye No</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.waybillNumber || ""}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, waybillNumber: e.target.value })
|
||||
}
|
||||
value={formData.waybillNumber || ''}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Cari Hesap
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Cari Hesap</label>
|
||||
<select
|
||||
value={formData.currentAccountId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, currentAccountId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
required
|
||||
>
|
||||
|
|
@ -295,12 +268,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Fatura Tarihi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Fatura Tarihi</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.invoiceDate?.toISOString().split("T")[0]}
|
||||
value={formData.invoiceDate?.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -313,12 +284,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Vade Tarihi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Vade Tarihi</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.dueDate?.toISOString().split("T")[0]}
|
||||
value={formData.dueDate?.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -333,9 +302,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
|
||||
{/* Invoice Items */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
Fatura Kalemleri
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">Fatura Kalemleri</h3>
|
||||
|
||||
{/* Add New Item */}
|
||||
<div className="bg-gray-50 p-3 rounded-lg mb-3">
|
||||
|
|
@ -346,21 +313,17 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newItem.description || ""}
|
||||
onChange={(e) =>
|
||||
setNewItem({ ...newItem, description: e.target.value })
|
||||
}
|
||||
value={newItem.description || ''}
|
||||
onChange={(e) => 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"
|
||||
placeholder="Ürün/Hizmet açıklaması"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Miktar
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Miktar</label>
|
||||
<input
|
||||
type="number"
|
||||
value={newItem.quantity || ""}
|
||||
value={newItem.quantity || ''}
|
||||
onChange={(e) =>
|
||||
setNewItem({
|
||||
...newItem,
|
||||
|
|
@ -378,7 +341,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="number"
|
||||
value={newItem.unitPrice || ""}
|
||||
value={newItem.unitPrice || ''}
|
||||
onChange={(e) =>
|
||||
setNewItem({
|
||||
...newItem,
|
||||
|
|
@ -391,11 +354,9 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
KDV (%)
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">KDV (%)</label>
|
||||
<select
|
||||
value={newItem.taxRate || 18}
|
||||
value={newItem.taxRate || 20}
|
||||
onChange={(e) =>
|
||||
setNewItem({
|
||||
...newItem,
|
||||
|
|
@ -408,6 +369,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
<option value={1}>1%</option>
|
||||
<option value={8}>8%</option>
|
||||
<option value={18}>18%</option>
|
||||
<option value={20}>20%</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-end">
|
||||
|
|
@ -452,18 +414,14 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
<tbody className="divide-y divide-gray-200">
|
||||
{formData.items.map((item) => (
|
||||
<tr key={item.id} className="text-sm">
|
||||
<td className="px-3 py-2 text-gray-900">
|
||||
{item.description}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-gray-900">{item.description}</td>
|
||||
<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-right">
|
||||
{formatCurrency(item.unitPrice)}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-gray-900 text-right">
|
||||
%{item.taxRate}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-gray-900 text-right">%{item.taxRate}</td>
|
||||
<td className="px-3 py-2 text-gray-900 text-right font-medium">
|
||||
{formatCurrency(item.lineTotal)}
|
||||
</td>
|
||||
|
|
@ -488,14 +446,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
<div className="bg-gray-50 p-4 rounded-lg mb-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Notlar
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Notlar</label>
|
||||
<textarea
|
||||
value={formData.notes || ""}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, notes: e.target.value })
|
||||
}
|
||||
value={formData.notes || ''}
|
||||
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
|
||||
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"
|
||||
placeholder="Fatura ile ilgili notlar..."
|
||||
|
|
@ -504,9 +458,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">Ara Toplam:</span>
|
||||
<span className="font-medium">
|
||||
{formatCurrency(formData.subtotal || 0)}
|
||||
</span>
|
||||
<span className="font-medium">{formatCurrency(formData.subtotal || 0)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">İndirim:</span>
|
||||
|
|
@ -516,15 +468,11 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
|||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">KDV:</span>
|
||||
<span className="font-medium">
|
||||
{formatCurrency(formData.taxAmount || 0)}
|
||||
</span>
|
||||
<span className="font-medium">{formatCurrency(formData.taxAmount || 0)}</span>
|
||||
</div>
|
||||
<div className="border-t pt-3">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-base font-semibold text-gray-900">
|
||||
Genel Toplam:
|
||||
</span>
|
||||
<span className="text-base font-semibold text-gray-900">Genel Toplam:</span>
|
||||
<span className="text-base font-bold text-blue-600">
|
||||
{formatCurrency(formData.totalAmount || 0)}
|
||||
</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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{invoice ? "Güncelle" : "Kaydet"}
|
||||
{invoice ? 'Güncelle' : 'Kaydet'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default InvoiceForm;
|
||||
export default InvoiceForm
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useState } from 'react'
|
||||
import {
|
||||
FaPlus,
|
||||
FaSearch,
|
||||
|
|
@ -8,15 +8,10 @@ import {
|
|||
FaFileAlt,
|
||||
FaEdit,
|
||||
FaSave,
|
||||
} from "react-icons/fa";
|
||||
import {
|
||||
FiInvoice,
|
||||
InvoiceTypeEnum,
|
||||
InvoiceStatusEnum,
|
||||
PaymentStatusEnum,
|
||||
} from "../../../types/fi";
|
||||
import DataTable, { Column } from "../../../components/common/DataTable";
|
||||
import Widget from "../../../components/common/Widget";
|
||||
} from 'react-icons/fa'
|
||||
import { FiInvoice, InvoiceTypeEnum, InvoiceStatusEnum, PaymentStatusEnum } from '../../../types/fi'
|
||||
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||
import Widget from '../../../components/common/Widget'
|
||||
import {
|
||||
getInvoiceTypeColor,
|
||||
getInvoiceTypeText,
|
||||
|
|
@ -24,15 +19,15 @@ import {
|
|||
getInvoiceStatusText,
|
||||
getPaymentStatusColor,
|
||||
getPaymentStatusText,
|
||||
} from "../../../utils/erp";
|
||||
} from '../../../utils/erp'
|
||||
|
||||
interface InvoiceManagementProps {
|
||||
invoices: FiInvoice[];
|
||||
onAdd: () => void;
|
||||
onEdit: (invoice: FiInvoice) => void;
|
||||
onConvertFromWaybill: () => void;
|
||||
onCreatePayment: (invoice: FiInvoice) => void;
|
||||
onViewDetails: (invoice: FiInvoice) => void;
|
||||
invoices: FiInvoice[]
|
||||
onAdd: () => void
|
||||
onEdit: (invoice: FiInvoice) => void
|
||||
onConvertFromWaybill: () => void
|
||||
onCreatePayment: (invoice: FiInvoice) => void
|
||||
onViewDetails: (invoice: FiInvoice) => void
|
||||
}
|
||||
|
||||
const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||
|
|
@ -43,103 +38,85 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
onCreatePayment,
|
||||
onViewDetails,
|
||||
}) => {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [selectedType, setSelectedType] = useState<InvoiceTypeEnum | "all">(
|
||||
"all"
|
||||
);
|
||||
const [selectedStatus, setSelectedStatus] = useState<
|
||||
InvoiceStatusEnum | "all"
|
||||
>("all");
|
||||
const [selectedPaymentStatus, setSelectedPaymentStatus] = useState<
|
||||
PaymentStatusEnum | "all"
|
||||
>("all");
|
||||
const [sortBy, setSortBy] = useState<"date" | "amount" | "dueDate">("date");
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [selectedType, setSelectedType] = useState<InvoiceTypeEnum | 'all'>('all')
|
||||
const [selectedStatus, setSelectedStatus] = useState<InvoiceStatusEnum | 'all'>('all')
|
||||
const [selectedPaymentStatus, setSelectedPaymentStatus] = useState<PaymentStatusEnum | 'all'>(
|
||||
'all',
|
||||
)
|
||||
const [sortBy, setSortBy] = useState<'date' | 'amount' | 'dueDate'>('date')
|
||||
|
||||
const filteredInvoices = invoices
|
||||
.filter((invoice) => {
|
||||
if (
|
||||
searchTerm &&
|
||||
!invoice.invoiceNumber
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()) &&
|
||||
!invoice.currentAccount?.accountCode
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()) &&
|
||||
!invoice.invoiceNumber.toLowerCase().includes(searchTerm.toLowerCase()) &&
|
||||
!invoice.currentAccount?.accountCode?.toLowerCase().includes(searchTerm.toLowerCase()) &&
|
||||
!invoice.waybillNumber?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (selectedType !== "all" && invoice.invoiceType !== selectedType) {
|
||||
return false;
|
||||
if (selectedType !== 'all' && invoice.invoiceType !== selectedType) {
|
||||
return false
|
||||
}
|
||||
if (selectedStatus !== "all" && invoice.status !== selectedStatus) {
|
||||
return false;
|
||||
if (selectedStatus !== 'all' && invoice.status !== selectedStatus) {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
selectedPaymentStatus !== "all" &&
|
||||
invoice.paymentStatus !== selectedPaymentStatus
|
||||
) {
|
||||
return false;
|
||||
if (selectedPaymentStatus !== 'all' && invoice.paymentStatus !== selectedPaymentStatus) {
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
})
|
||||
.sort((a, b) => {
|
||||
switch (sortBy) {
|
||||
case "date":
|
||||
return (
|
||||
new Date(b.invoiceDate).getTime() -
|
||||
new Date(a.invoiceDate).getTime()
|
||||
);
|
||||
case "amount":
|
||||
return b.totalAmount - a.totalAmount;
|
||||
case "dueDate":
|
||||
return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime();
|
||||
case 'date':
|
||||
return new Date(b.invoiceDate).getTime() - new Date(a.invoiceDate).getTime()
|
||||
case 'amount':
|
||||
return b.totalAmount - a.totalAmount
|
||||
case 'dueDate':
|
||||
return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime()
|
||||
default:
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const getDaysUntilDue = (dueDate: Date) => {
|
||||
const today = new Date();
|
||||
const due = new Date(dueDate);
|
||||
const diffTime = due.getTime() - today.getTime();
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
return diffDays;
|
||||
};
|
||||
const today = new Date()
|
||||
const due = new Date(dueDate)
|
||||
const diffTime = due.getTime() - today.getTime()
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||
return diffDays
|
||||
}
|
||||
|
||||
const formatCurrency = (amount: number) => {
|
||||
return amount.toLocaleString("tr-TR", {
|
||||
style: "currency",
|
||||
currency: "TRY",
|
||||
return amount.toLocaleString('tr-TR', {
|
||||
style: 'currency',
|
||||
currency: 'TRY',
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
const columns: Column<FiInvoice>[] = [
|
||||
{
|
||||
key: "invoiceNumber",
|
||||
header: "Fatura No",
|
||||
key: 'invoiceNumber',
|
||||
header: 'Fatura No',
|
||||
sortable: true,
|
||||
render: (invoice: FiInvoice) => (
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
{invoice.invoiceNumber}
|
||||
</div>
|
||||
<div className="font-medium text-gray-900">{invoice.invoiceNumber}</div>
|
||||
{invoice.waybillNumber && (
|
||||
<div className="text-sm text-gray-500">
|
||||
İrs: {invoice.waybillNumber}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">İrs: {invoice.waybillNumber}</div>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
header: "Tür",
|
||||
key: 'type',
|
||||
header: 'Tür',
|
||||
render: (invoice: FiInvoice) => (
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
|
||||
invoice.invoiceType
|
||||
invoice.invoiceType,
|
||||
)}`}
|
||||
>
|
||||
{getInvoiceTypeText(invoice.invoiceType)}
|
||||
|
|
@ -147,61 +124,54 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
),
|
||||
},
|
||||
{
|
||||
key: "currentAccount",
|
||||
header: "Cari Hesap",
|
||||
key: 'currentAccount',
|
||||
header: 'Cari Hesap',
|
||||
render: (invoice: FiInvoice) => (
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
{invoice.currentAccount?.accountCode || "Bilinmeyen"}
|
||||
{invoice.currentAccount?.accountCode || 'Bilinmeyen'}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "dates",
|
||||
header: "Tarihler",
|
||||
key: 'dates',
|
||||
header: 'Tarihler',
|
||||
render: (invoice: FiInvoice) => {
|
||||
const daysUntilDue = getDaysUntilDue(invoice.dueDate);
|
||||
const daysUntilDue = getDaysUntilDue(invoice.dueDate)
|
||||
return (
|
||||
<div className="text-sm">
|
||||
<div className="flex items-center gap-1">
|
||||
<FaCalendar className="w-3 h-3 text-gray-400" />
|
||||
<span>
|
||||
Fatura:{" "}
|
||||
{new Date(invoice.invoiceDate).toLocaleDateString("tr-TR")}
|
||||
</span>
|
||||
<span>Fatura: {new Date(invoice.invoiceDate).toLocaleDateString('tr-TR')}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<FaClock className="w-3 h-3 text-gray-400" />
|
||||
<span
|
||||
className={
|
||||
daysUntilDue < 0
|
||||
? "text-red-600"
|
||||
? 'text-red-600'
|
||||
: daysUntilDue <= 7
|
||||
? "text-orange-600"
|
||||
: "text-gray-600"
|
||||
? 'text-orange-600'
|
||||
: 'text-gray-600'
|
||||
}
|
||||
>
|
||||
Vade: {new Date(invoice.dueDate).toLocaleDateString("tr-TR")}
|
||||
Vade: {new Date(invoice.dueDate).toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
{daysUntilDue < 0 && (
|
||||
<div className="text-xs text-red-600">
|
||||
{Math.abs(daysUntilDue)} gün gecikme
|
||||
</div>
|
||||
<div className="text-xs text-red-600">{Math.abs(daysUntilDue)} gün gecikme</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "amounts",
|
||||
header: "Tutarlar",
|
||||
key: 'amounts',
|
||||
header: 'Tutarlar',
|
||||
render: (invoice: FiInvoice) => (
|
||||
<div className="text-right">
|
||||
<div className="font-medium text-gray-900">
|
||||
{formatCurrency(invoice.totalAmount)}
|
||||
</div>
|
||||
<div className="font-medium text-gray-900">{formatCurrency(invoice.totalAmount)}</div>
|
||||
{invoice.paidAmount > 0 && (
|
||||
<div className="text-sm text-green-600">
|
||||
Ödenen: {formatCurrency(invoice.paidAmount)}
|
||||
|
|
@ -216,13 +186,13 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
),
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
header: "Durum",
|
||||
key: 'status',
|
||||
header: 'Durum',
|
||||
render: (invoice: FiInvoice) => (
|
||||
<div className="space-y-1">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceStatusColor(
|
||||
invoice.status
|
||||
invoice.status,
|
||||
)}`}
|
||||
>
|
||||
{getInvoiceStatusText(invoice.status)}
|
||||
|
|
@ -230,7 +200,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
<br />
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
|
||||
invoice.paymentStatus
|
||||
invoice.paymentStatus,
|
||||
)}`}
|
||||
>
|
||||
{getPaymentStatusText(invoice.paymentStatus)}
|
||||
|
|
@ -239,8 +209,8 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
),
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
header: "İşlemler",
|
||||
key: 'actions',
|
||||
header: 'İşlemler',
|
||||
render: (invoice: FiInvoice) => (
|
||||
<div className="flex gap-1">
|
||||
{invoice.paymentStatus !== PaymentStatusEnum.Paid && (
|
||||
|
|
@ -269,37 +239,33 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
// Calculate statistics
|
||||
const totalInvoices = invoices.length;
|
||||
const totalInvoices = invoices.length
|
||||
const totalSalesAmount = invoices
|
||||
.filter((i) => i.invoiceType === InvoiceTypeEnum.Sales)
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0);
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0)
|
||||
const totalPurchaseAmount = invoices
|
||||
.filter((i) => i.invoiceType === InvoiceTypeEnum.Purchase)
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0);
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0)
|
||||
const totalUnpaidAmount = invoices
|
||||
.filter((i) => i.paymentStatus !== PaymentStatusEnum.Paid)
|
||||
.reduce((sum, i) => sum + i.remainingAmount, 0);
|
||||
.reduce((sum, i) => sum + i.remainingAmount, 0)
|
||||
|
||||
// Overdue invoices
|
||||
const overdueInvoices = invoices.filter(
|
||||
(i) =>
|
||||
i.paymentStatus !== PaymentStatusEnum.Paid &&
|
||||
new Date(i.dueDate) < new Date()
|
||||
);
|
||||
(i) => i.paymentStatus !== PaymentStatusEnum.Paid && new Date(i.dueDate) < new Date(),
|
||||
)
|
||||
|
||||
// Payment status distribution
|
||||
const paymentDistribution = Object.values(PaymentStatusEnum).map(
|
||||
(status) => ({
|
||||
status,
|
||||
count: invoices.filter((i) => i.paymentStatus === status).length,
|
||||
amount: invoices
|
||||
.filter((i) => i.paymentStatus === status)
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0),
|
||||
})
|
||||
);
|
||||
const paymentDistribution = Object.values(PaymentStatusEnum).map((status) => ({
|
||||
status,
|
||||
count: invoices.filter((i) => i.paymentStatus === status).length,
|
||||
amount: invoices
|
||||
.filter((i) => i.paymentStatus === status)
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0),
|
||||
}))
|
||||
|
||||
// Invoice type distribution
|
||||
const typeDistribution = Object.values(InvoiceTypeEnum).map((type) => ({
|
||||
|
|
@ -308,7 +274,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
amount: invoices
|
||||
.filter((i) => i.invoiceType === type)
|
||||
.reduce((sum, i) => sum + i.totalAmount, 0),
|
||||
}));
|
||||
}))
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
|
|
@ -316,9 +282,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-gray-900">Fatura Yönetimi</h2>
|
||||
<p className="text-gray-600">
|
||||
Alış ve satış faturaları yönetimi
|
||||
</p>
|
||||
<p className="text-gray-600">Alış ve satış faturaları yönetimi</p>
|
||||
</div>
|
||||
<div className="flex gap-2 text-sm">
|
||||
<button
|
||||
|
|
@ -340,12 +304,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<Widget
|
||||
title="Toplam Fatura"
|
||||
value={totalInvoices}
|
||||
color="blue"
|
||||
icon="FaFileAlt"
|
||||
/>
|
||||
<Widget title="Toplam Fatura" value={totalInvoices} color="blue" icon="FaFileAlt" />
|
||||
|
||||
<Widget
|
||||
title="Satış Tutarı"
|
||||
|
|
@ -372,16 +331,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
{/* Distribution Charts */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
Fatura Türü Dağılımı
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">Fatura Türü Dağılımı</h3>
|
||||
<div className="space-y-2">
|
||||
{typeDistribution.map(({ type, count, amount }) => (
|
||||
<div key={type} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
|
||||
type
|
||||
type,
|
||||
)}`}
|
||||
>
|
||||
{getInvoiceTypeText(type)}
|
||||
|
|
@ -399,16 +356,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
Ödeme Durumu Dağılımı
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">Ödeme Durumu Dağılımı</h3>
|
||||
<div className="space-y-2">
|
||||
{paymentDistribution.map(({ status, count, amount }) => (
|
||||
<div key={status} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
|
||||
status
|
||||
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="flex items-center gap-2">
|
||||
<FaExclamationTriangle className="w-5 h-5 text-red-600" />
|
||||
<h3 className="text-base font-semibold text-red-900">
|
||||
Vadesi Geçmiş Faturalar
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-red-900">Vadesi Geçmiş Faturalar</h3>
|
||||
</div>
|
||||
<p className="text-sm text-red-700 mt-1">
|
||||
{overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam
|
||||
tutar:{" "}
|
||||
{formatCurrency(
|
||||
overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0)
|
||||
)}
|
||||
{overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam tutar:{' '}
|
||||
{formatCurrency(overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0))}
|
||||
</p>
|
||||
<div className="mt-2 space-y-1.5">
|
||||
{overdueInvoices.slice(0, 3).map((invoice) => {
|
||||
const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate));
|
||||
const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate))
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -466,7 +416,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -487,9 +437,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={selectedType}
|
||||
onChange={(e) =>
|
||||
setSelectedType(e.target.value as InvoiceTypeEnum | "all")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="all">Tüm Türler</option>
|
||||
|
|
@ -502,9 +450,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={selectedStatus}
|
||||
onChange={(e) =>
|
||||
setSelectedStatus(e.target.value as InvoiceStatusEnum | "all")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
|
|
@ -517,11 +463,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={selectedPaymentStatus}
|
||||
onChange={(e) =>
|
||||
setSelectedPaymentStatus(
|
||||
e.target.value as PaymentStatusEnum | "all"
|
||||
)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="all">Tüm Ödeme Durumları</option>
|
||||
|
|
@ -534,9 +476,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={sortBy}
|
||||
onChange={(e) =>
|
||||
setSortBy(e.target.value as "date" | "amount" | "dueDate")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="date">Tarihe Göre</option>
|
||||
|
|
@ -553,16 +493,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
|||
{filteredInvoices.length === 0 && (
|
||||
<div className="text-center py-10">
|
||||
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
|
||||
<h3 className="text-base font-medium text-gray-900 mb-2">
|
||||
Fatura bulunamadı
|
||||
</h3>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-2">Fatura bulunamadı</h3>
|
||||
<p className="text-sm text-gray-500">
|
||||
Yeni bir fatura ekleyin veya arama kriterlerinizi değiştirin.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default InvoiceManagement;
|
||||
export default InvoiceManagement
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaFileAlt, FaSave, FaTimes } from "react-icons/fa";
|
||||
import {
|
||||
PromissoryNote,
|
||||
NoteTypeEnum,
|
||||
NoteStatusEnum,
|
||||
FiCurrentAccount,
|
||||
} from "../../../types/fi";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaFileAlt, FaSave, FaTimes } from 'react-icons/fa'
|
||||
import { PromissoryNote, NoteStatusEnum, FiCurrentAccount, TypeEnum } from '../../../types/fi'
|
||||
import { getNoteStatusText, getTypeText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface PromissoryNoteFormProps {
|
||||
note?: PromissoryNote;
|
||||
currentAccounts: FiCurrentAccount[];
|
||||
onSave: (
|
||||
note: Omit<PromissoryNote, "id" | "creationTime" | "lastModificationTime">
|
||||
) => void;
|
||||
onCancel: () => void;
|
||||
isOpen: boolean;
|
||||
note?: PromissoryNote
|
||||
currentAccounts: FiCurrentAccount[]
|
||||
onSave: (note: Omit<PromissoryNote, 'id' | 'creationTime' | 'lastModificationTime'>) => void
|
||||
onCancel: () => void
|
||||
isOpen: boolean
|
||||
}
|
||||
|
||||
const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||
|
|
@ -25,21 +20,21 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
isOpen,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState({
|
||||
noteNumber: "",
|
||||
drawerName: "",
|
||||
payeeName: "",
|
||||
currentAccountId: "",
|
||||
issueDate: new Date().toISOString().split("T")[0],
|
||||
dueDate: new Date().toISOString().split("T")[0],
|
||||
noteNumber: '',
|
||||
drawerName: '',
|
||||
payeeName: '',
|
||||
currentAccountId: '',
|
||||
issueDate: new Date().toISOString().split('T')[0],
|
||||
dueDate: new Date().toISOString().split('T')[0],
|
||||
amount: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: NoteStatusEnum.InHand,
|
||||
type: NoteTypeEnum.Received,
|
||||
location: "",
|
||||
notes: "",
|
||||
});
|
||||
type: TypeEnum.Received,
|
||||
location: '',
|
||||
notes: '',
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||
|
||||
useEffect(() => {
|
||||
if (note) {
|
||||
|
|
@ -47,60 +42,60 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
noteNumber: note.noteNumber,
|
||||
drawerName: note.drawerName,
|
||||
payeeName: note.payeeName,
|
||||
currentAccountId: note.currentAccountId || "",
|
||||
issueDate: new Date(note.issueDate).toISOString().split("T")[0],
|
||||
dueDate: new Date(note.dueDate).toISOString().split("T")[0],
|
||||
currentAccountId: note.currentAccountId || '',
|
||||
issueDate: new Date(note.issueDate).toISOString().split('T')[0],
|
||||
dueDate: new Date(note.dueDate).toISOString().split('T')[0],
|
||||
amount: note.amount,
|
||||
currency: note.currency,
|
||||
status: note.status,
|
||||
type: note.type,
|
||||
location: note.location || "",
|
||||
notes: note.notes || "",
|
||||
});
|
||||
location: note.location || '',
|
||||
notes: note.notes || '',
|
||||
})
|
||||
} else {
|
||||
setFormData({
|
||||
noteNumber: "",
|
||||
drawerName: "",
|
||||
payeeName: "",
|
||||
currentAccountId: "",
|
||||
issueDate: new Date().toISOString().split("T")[0],
|
||||
dueDate: new Date().toISOString().split("T")[0],
|
||||
noteNumber: '',
|
||||
drawerName: '',
|
||||
payeeName: '',
|
||||
currentAccountId: '',
|
||||
issueDate: new Date().toISOString().split('T')[0],
|
||||
dueDate: new Date().toISOString().split('T')[0],
|
||||
amount: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: NoteStatusEnum.InHand,
|
||||
type: NoteTypeEnum.Received,
|
||||
location: "",
|
||||
notes: "",
|
||||
});
|
||||
type: TypeEnum.Received,
|
||||
location: '',
|
||||
notes: '',
|
||||
})
|
||||
}
|
||||
setErrors({});
|
||||
}, [note, isOpen]);
|
||||
setErrors({})
|
||||
}, [note, isOpen])
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.noteNumber.trim()) {
|
||||
newErrors.noteNumber = "Senet numarası gereklidir";
|
||||
newErrors.noteNumber = 'Senet numarası gereklidir'
|
||||
}
|
||||
if (!formData.drawerName.trim()) {
|
||||
newErrors.drawerName = "Keşideci adı gereklidir";
|
||||
newErrors.drawerName = 'Keşideci adı gereklidir'
|
||||
}
|
||||
if (!formData.payeeName.trim()) {
|
||||
newErrors.payeeName = "Lehtar adı gereklidir";
|
||||
newErrors.payeeName = 'Lehtar adı gereklidir'
|
||||
}
|
||||
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)) {
|
||||
newErrors.dueDate = "Vade tarihi düzenleme tarihinden sonra olmalıdır";
|
||||
newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (validateForm()) {
|
||||
const noteData = {
|
||||
...formData,
|
||||
|
|
@ -109,22 +104,19 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
currentAccount: formData.currentAccountId
|
||||
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
|
||||
: undefined,
|
||||
};
|
||||
onSave(noteData);
|
||||
}
|
||||
onSave(noteData)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleInputChange = (
|
||||
field: string,
|
||||
value: string | number | NoteTypeEnum | NoteStatusEnum
|
||||
) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
const handleInputChange = (field: string, value: string | number | TypeEnum | NoteStatusEnum) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }))
|
||||
if (errors[field]) {
|
||||
setErrors((prev) => ({ ...prev, [field]: "" }));
|
||||
setErrors((prev) => ({ ...prev, [field]: '' }))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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">
|
||||
<FaFileAlt className="w-5 h-5 text-green-600" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
{note ? "Senet Düzenle" : "Yeni Senet"}
|
||||
{note ? 'Senet Düzenle' : 'Yeni Senet'}
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
className="p-2 hover:bg-gray-100 rounded-md"
|
||||
>
|
||||
<button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
|
||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -154,11 +143,9 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={formData.noteNumber}
|
||||
onChange={(e) =>
|
||||
handleInputChange("noteNumber", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.noteNumber ? "border-red-500" : "border-gray-300"
|
||||
errors.noteNumber ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Senet numarasını giriniz"
|
||||
/>
|
||||
|
|
@ -168,100 +155,77 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Tür *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
|
||||
<select
|
||||
value={formData.type}
|
||||
onChange={(e) =>
|
||||
handleInputChange("type", e.target.value as NoteTypeEnum)
|
||||
}
|
||||
onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
|
||||
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>
|
||||
<option value={NoteTypeEnum.Issued}>Verilen Senet</option>
|
||||
{Object.values(TypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Durum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||
<select
|
||||
value={formData.status}
|
||||
onChange={(e) =>
|
||||
handleInputChange("status", e.target.value as NoteStatusEnum)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value={NoteStatusEnum.InHand}>Elde</option>
|
||||
<option value={NoteStatusEnum.Collected}>Tahsil Edildi</option>
|
||||
<option value={NoteStatusEnum.Overdue}>Vadesi Geçmiş</option>
|
||||
<option value={NoteStatusEnum.Endorsed}>Ciro Edildi</option>
|
||||
<option value={NoteStatusEnum.Cancelled}>İptal</option>
|
||||
{Object.values(NoteStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getNoteStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Taraf Bilgileri */}
|
||||
<div className="bg-gray-50 p-3 rounded-lg">
|
||||
<h3 className="text-base font-medium text-gray-900 mb-3">
|
||||
Taraf Bilgileri
|
||||
</h3>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Keşideci *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.drawerName}
|
||||
onChange={(e) =>
|
||||
handleInputChange("drawerName", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.drawerName ? "border-red-500" : "border-gray-300"
|
||||
errors.drawerName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Keşideci adını giriniz"
|
||||
/>
|
||||
{errors.drawerName && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.drawerName}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Lehtar *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.payeeName}
|
||||
onChange={(e) =>
|
||||
handleInputChange("payeeName", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.payeeName ? "border-red-500" : "border-gray-300"
|
||||
errors.payeeName ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Lehtar adını giriniz"
|
||||
/>
|
||||
{errors.payeeName && (
|
||||
<p className="text-red-500 text-xs mt-1">
|
||||
{errors.payeeName}
|
||||
</p>
|
||||
<p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Cari Hesap
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
|
||||
<select
|
||||
value={formData.currentAccountId}
|
||||
onChange={(e) =>
|
||||
handleInputChange("currentAccountId", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Cari hesap seçiniz</option>
|
||||
|
|
@ -278,39 +242,33 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
{/* Tutar ve Tarih Bilgileri */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Tutar *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.amount}
|
||||
onChange={(e) =>
|
||||
handleInputChange("amount", parseFloat(e.target.value) || 0)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.amount ? "border-red-500" : "border-gray-300"
|
||||
errors.amount ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="0.00"
|
||||
/>
|
||||
{errors.amount && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.amount}</p>
|
||||
)}
|
||||
{errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Para Birimi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||
<select
|
||||
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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -321,38 +279,32 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
<input
|
||||
type="date"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Vade Tarihi *
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
|
||||
<input
|
||||
type="date"
|
||||
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 ${
|
||||
errors.dueDate ? "border-red-500" : "border-gray-300"
|
||||
errors.dueDate ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
/>
|
||||
{errors.dueDate && (
|
||||
<p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>
|
||||
)}
|
||||
{errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Konum */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Konum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Konum</label>
|
||||
<input
|
||||
type="text"
|
||||
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"
|
||||
placeholder="Senetin bulunduğu konum"
|
||||
/>
|
||||
|
|
@ -360,12 +312,10 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
|||
|
||||
{/* Notlar */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Notlar
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
|
||||
<textarea
|
||||
value={formData.notes}
|
||||
onChange={(e) => handleInputChange("notes", e.target.value)}
|
||||
onChange={(e) => handleInputChange('notes', e.target.value)}
|
||||
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"
|
||||
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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{note ? "Güncelle" : "Kaydet"}
|
||||
{note ? 'Güncelle' : 'Kaydet'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default PromissoryNoteForm;
|
||||
export default PromissoryNoteForm
|
||||
|
|
|
|||
|
|
@ -1,178 +1,161 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaSave, FaTimes, FaPlus, FaTrash, FaTruck } from "react-icons/fa";
|
||||
import {
|
||||
FiWaybill,
|
||||
FiWaybillItem,
|
||||
WaybillTypeEnum,
|
||||
WaybillStatusEnum,
|
||||
} from "../../../types/fi";
|
||||
import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaSave, FaTimes, FaPlus, FaTrash, FaTruck } from 'react-icons/fa'
|
||||
import { FiWaybill, FiWaybillItem, WaybillTypeEnum, WaybillStatusEnum } from '../../../types/fi'
|
||||
import { mockCurrentAccounts } from '../../../mocks/mockCurrentAccounts'
|
||||
import { getWaybillStatusText, getWaybillTypeText } from '@/utils/erp'
|
||||
|
||||
interface WaybillFormProps {
|
||||
waybill?: FiWaybill;
|
||||
onSave: (waybill: Partial<FiWaybill>) => void;
|
||||
onCancel: () => void;
|
||||
isVisible: boolean;
|
||||
waybill?: FiWaybill
|
||||
onSave: (waybill: Partial<FiWaybill>) => void
|
||||
onCancel: () => void
|
||||
isVisible: boolean
|
||||
}
|
||||
|
||||
const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||
waybill,
|
||||
onSave,
|
||||
onCancel,
|
||||
isVisible,
|
||||
}) => {
|
||||
const WaybillForm: React.FC<WaybillFormProps> = ({ waybill, onSave, onCancel, isVisible }) => {
|
||||
const [formData, setFormData] = useState<Partial<FiWaybill>>({
|
||||
waybillNumber: "",
|
||||
waybillNumber: '',
|
||||
waybillType: WaybillTypeEnum.Outgoing,
|
||||
currentAccountId: "",
|
||||
currentAccountId: '',
|
||||
waybillDate: new Date(),
|
||||
deliveryDate: new Date(),
|
||||
subtotal: 0,
|
||||
taxAmount: 0,
|
||||
discountAmount: 0,
|
||||
totalAmount: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
status: WaybillStatusEnum.Draft,
|
||||
isInvoiced: false,
|
||||
items: [],
|
||||
deliveryAddress: "",
|
||||
receiverName: "",
|
||||
receiverPhone: "",
|
||||
carrierCompany: "",
|
||||
trackingNumber: "",
|
||||
notes: "",
|
||||
});
|
||||
deliveryAddress: '',
|
||||
receiverName: '',
|
||||
receiverPhone: '',
|
||||
carrierCompany: '',
|
||||
trackingNumber: '',
|
||||
notes: '',
|
||||
})
|
||||
|
||||
const [newItem, setNewItem] = useState<Partial<FiWaybillItem>>({
|
||||
description: "",
|
||||
description: '',
|
||||
quantity: 1,
|
||||
unitPrice: 0,
|
||||
taxRate: 18,
|
||||
discountRate: 0,
|
||||
unit: "Adet",
|
||||
});
|
||||
unit: 'Adet',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (waybill) {
|
||||
setFormData({
|
||||
...waybill,
|
||||
waybillDate: new Date(waybill.waybillDate),
|
||||
deliveryDate: waybill.deliveryDate
|
||||
? new Date(waybill.deliveryDate)
|
||||
: new Date(),
|
||||
});
|
||||
deliveryDate: waybill.deliveryDate ? new Date(waybill.deliveryDate) : new Date(),
|
||||
})
|
||||
} else {
|
||||
// Generate new waybill number
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
||||
const waybillNumber = `IRS${year}${month}${String(
|
||||
Math.floor(Math.random() * 10000)
|
||||
).padStart(4, "0")}`;
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const waybillNumber = `IRS${year}${month}${String(Math.floor(Math.random() * 10000)).padStart(
|
||||
4,
|
||||
'0',
|
||||
)}`
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
waybillNumber,
|
||||
waybillDate: now,
|
||||
deliveryDate: now,
|
||||
}));
|
||||
}))
|
||||
}
|
||||
}, [waybill]);
|
||||
}, [waybill])
|
||||
|
||||
const calculateItemTotal = (item: Partial<FiWaybillItem>) => {
|
||||
const subtotal = (item.quantity || 0) * (item.unitPrice || 0);
|
||||
const discountAmount = subtotal * ((item.discountRate || 0) / 100);
|
||||
const taxableAmount = subtotal - discountAmount;
|
||||
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100);
|
||||
return taxableAmount + taxAmount;
|
||||
};
|
||||
const subtotal = (item.quantity || 0) * (item.unitPrice || 0)
|
||||
const discountAmount = subtotal * ((item.discountRate || 0) / 100)
|
||||
const taxableAmount = subtotal - discountAmount
|
||||
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100)
|
||||
return taxableAmount + taxAmount
|
||||
}
|
||||
|
||||
const calculateWaybillTotals = (items: FiWaybillItem[]) => {
|
||||
const subtotal = items.reduce(
|
||||
(sum, item) => sum + item.quantity * item.unitPrice,
|
||||
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);
|
||||
const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 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 {
|
||||
subtotal,
|
||||
discountAmount,
|
||||
taxAmount,
|
||||
totalAmount,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const handleAddItem = () => {
|
||||
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
|
||||
alert("Lütfen ürün bilgilerini doldurun");
|
||||
return;
|
||||
alert('Lütfen ürün bilgilerini doldurun')
|
||||
return
|
||||
}
|
||||
|
||||
const subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0);
|
||||
const discountAmount = subtotal * ((newItem.discountRate || 0) / 100);
|
||||
const taxableAmount = subtotal - discountAmount;
|
||||
const taxAmount = taxableAmount * ((newItem.taxRate || 0) / 100);
|
||||
const subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0)
|
||||
const discountAmount = subtotal * ((newItem.discountRate || 0) / 100)
|
||||
const taxableAmount = subtotal - discountAmount
|
||||
const taxAmount = taxableAmount * ((newItem.taxRate || 0) / 100)
|
||||
|
||||
const item: FiWaybillItem = {
|
||||
id: Date.now().toString(),
|
||||
waybillId: formData.id || "",
|
||||
waybillId: formData.id || '',
|
||||
description: newItem.description!,
|
||||
quantity: newItem.quantity!,
|
||||
unitPrice: newItem.unitPrice!,
|
||||
unit: newItem.unit || "Adet",
|
||||
unit: newItem.unit || 'Adet',
|
||||
taxRate: newItem.taxRate || 18,
|
||||
discountRate: newItem.discountRate || 0,
|
||||
lineTotal: calculateItemTotal(newItem),
|
||||
discountAmount,
|
||||
taxAmount,
|
||||
netAmount: taxableAmount,
|
||||
};
|
||||
}
|
||||
|
||||
const updatedItems = [...(formData.items || []), item];
|
||||
const totals = calculateWaybillTotals(updatedItems);
|
||||
const updatedItems = [...(formData.items || []), item]
|
||||
const totals = calculateWaybillTotals(updatedItems)
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
items: updatedItems,
|
||||
...totals,
|
||||
}));
|
||||
}))
|
||||
|
||||
setNewItem({
|
||||
description: "",
|
||||
description: '',
|
||||
quantity: 1,
|
||||
unitPrice: 0,
|
||||
taxRate: 18,
|
||||
discountRate: 0,
|
||||
unit: "Adet",
|
||||
});
|
||||
};
|
||||
unit: 'Adet',
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemoveItem = (itemId: string) => {
|
||||
const updatedItems =
|
||||
formData.items?.filter((item) => item.id !== itemId) || [];
|
||||
const totals = calculateWaybillTotals(updatedItems);
|
||||
const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []
|
||||
const totals = calculateWaybillTotals(updatedItems)
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
items: updatedItems,
|
||||
...totals,
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (!formData.currentAccountId) {
|
||||
alert("Lütfen cari hesap seçin");
|
||||
return;
|
||||
alert('Lütfen cari hesap seçin')
|
||||
return
|
||||
}
|
||||
if (!formData.items?.length) {
|
||||
alert("Lütfen en az bir ürün ekleyin");
|
||||
return;
|
||||
alert('Lütfen en az bir ürün ekleyin')
|
||||
return
|
||||
}
|
||||
|
||||
onSave({
|
||||
|
|
@ -180,18 +163,18 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
id: waybill?.id || Date.now().toString(),
|
||||
creationTime: waybill?.creationTime || new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
const formatCurrency = (amount: number) => {
|
||||
return amount.toLocaleString("tr-TR", {
|
||||
style: "currency",
|
||||
currency: "TRY",
|
||||
return amount.toLocaleString('tr-TR', {
|
||||
style: 'currency',
|
||||
currency: 'TRY',
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
if (!isVisible) return null;
|
||||
if (!isVisible) return null
|
||||
|
||||
return (
|
||||
<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">
|
||||
<FaTruck className="w-5 h-5 text-blue-600" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
{waybill ? "İrsaliye Düzenle" : "Yeni İrsaliye"}
|
||||
{waybill ? 'İrsaliye Düzenle' : 'Yeni İrsaliye'}
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
|
|
@ -217,24 +200,18 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
{/* Basic Information */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
İrsaliye No
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye No</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.waybillNumber}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, waybillNumber: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
İrsaliye Türü
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye Türü</label>
|
||||
<select
|
||||
value={formData.waybillType}
|
||||
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"
|
||||
>
|
||||
<option value={WaybillTypeEnum.Outgoing}>
|
||||
Çıkış İrsaliyesi
|
||||
</option>
|
||||
<option value={WaybillTypeEnum.Incoming}>
|
||||
Giriş İrsaliyesi
|
||||
</option>
|
||||
<option value={WaybillTypeEnum.Transfer}>
|
||||
Transfer İrsaliyesi
|
||||
</option>
|
||||
<option value={WaybillTypeEnum.Return}>İade İrsaliyesi</option>
|
||||
{Object.values(WaybillTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getWaybillTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Durum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Durum</label>
|
||||
<select
|
||||
value={formData.status}
|
||||
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"
|
||||
>
|
||||
<option value={WaybillStatusEnum.Draft}>Taslak</option>
|
||||
<option value={WaybillStatusEnum.Confirmed}>Onaylandı</option>
|
||||
<option value={WaybillStatusEnum.Delivered}>
|
||||
Teslim Edildi
|
||||
</option>
|
||||
<option value={WaybillStatusEnum.Cancelled}>İptal</option>
|
||||
{Object.values(WaybillStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWaybillStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Cari Hesap
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Cari Hesap</label>
|
||||
<select
|
||||
value={formData.currentAccountId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, currentAccountId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
required
|
||||
>
|
||||
|
|
@ -308,7 +273,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.waybillDate?.toISOString().split("T")[0]}
|
||||
value={formData.waybillDate?.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -321,12 +286,10 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Teslim Tarihi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Teslim Tarihi</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.deliveryDate?.toISOString().split("T")[0]}
|
||||
value={formData.deliveryDate?.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -340,16 +303,14 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
|
||||
{/* Delivery Information */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
Teslimat Bilgileri
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">Teslimat Bilgileri</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Teslimat Adresi
|
||||
</label>
|
||||
<textarea
|
||||
value={formData.deliveryAddress || ""}
|
||||
value={formData.deliveryAddress || ''}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -362,15 +323,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</div>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Alıcı Adı
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Alıcı Adı</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.receiverName || ""}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, receiverName: e.target.value })
|
||||
}
|
||||
value={formData.receiverName || ''}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -380,7 +337,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.receiverPhone || ""}
|
||||
value={formData.receiverPhone || ''}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -397,10 +354,8 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.carrierCompany || ""}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, carrierCompany: e.target.value })
|
||||
}
|
||||
value={formData.carrierCompany || ''}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -410,10 +365,8 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.trackingNumber || ""}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, trackingNumber: e.target.value })
|
||||
}
|
||||
value={formData.trackingNumber || ''}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -422,9 +375,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
|
||||
{/* Waybill Items */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
İrsaliye Kalemleri
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">İrsaliye Kalemleri</h3>
|
||||
|
||||
{/* Add New Item */}
|
||||
<div className="bg-gray-50 p-3 rounded-lg mb-3">
|
||||
|
|
@ -435,21 +386,17 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newItem.description || ""}
|
||||
onChange={(e) =>
|
||||
setNewItem({ ...newItem, description: e.target.value })
|
||||
}
|
||||
value={newItem.description || ''}
|
||||
onChange={(e) => 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"
|
||||
placeholder="Ürün/Hizmet açıklaması"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Miktar
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Miktar</label>
|
||||
<input
|
||||
type="number"
|
||||
value={newItem.quantity || ""}
|
||||
value={newItem.quantity || ''}
|
||||
onChange={(e) =>
|
||||
setNewItem({
|
||||
...newItem,
|
||||
|
|
@ -462,15 +409,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Birim
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Birim</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newItem.unit || ""}
|
||||
onChange={(e) =>
|
||||
setNewItem({ ...newItem, unit: e.target.value })
|
||||
}
|
||||
value={newItem.unit || ''}
|
||||
onChange={(e) => 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"
|
||||
placeholder="Adet"
|
||||
/>
|
||||
|
|
@ -481,7 +424,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</label>
|
||||
<input
|
||||
type="number"
|
||||
value={newItem.unitPrice || ""}
|
||||
value={newItem.unitPrice || ''}
|
||||
onChange={(e) =>
|
||||
setNewItem({
|
||||
...newItem,
|
||||
|
|
@ -535,15 +478,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
<tbody className="divide-y divide-gray-200">
|
||||
{formData.items.map((item) => (
|
||||
<tr key={item.id} className="text-sm">
|
||||
<td className="px-3 py-2 text-gray-900">
|
||||
{item.description}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-gray-900">{item.description}</td>
|
||||
<td className="px-3 py-2 text-gray-900 text-right">
|
||||
{item.quantity.toLocaleString("tr-TR")}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-gray-900 text-center">
|
||||
{item.unit}
|
||||
{item.quantity.toLocaleString('tr-TR')}
|
||||
</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">
|
||||
{formatCurrency(item.unitPrice)}
|
||||
</td>
|
||||
|
|
@ -571,14 +510,10 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
<div className="bg-gray-50 p-4 rounded-lg mb-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Notlar
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Notlar</label>
|
||||
<textarea
|
||||
value={formData.notes || ""}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, notes: e.target.value })
|
||||
}
|
||||
value={formData.notes || ''}
|
||||
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
|
||||
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"
|
||||
placeholder="İrsaliye ile ilgili notlar..."
|
||||
|
|
@ -587,9 +522,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">Ara Toplam:</span>
|
||||
<span className="font-medium">
|
||||
{formatCurrency(formData.subtotal || 0)}
|
||||
</span>
|
||||
<span className="font-medium">{formatCurrency(formData.subtotal || 0)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">İndirim:</span>
|
||||
|
|
@ -599,15 +532,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
|||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">KDV:</span>
|
||||
<span className="font-medium">
|
||||
{formatCurrency(formData.taxAmount || 0)}
|
||||
</span>
|
||||
<span className="font-medium">{formatCurrency(formData.taxAmount || 0)}</span>
|
||||
</div>
|
||||
<div className="border-t pt-3">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-base font-semibold text-gray-900">
|
||||
Genel Toplam:
|
||||
</span>
|
||||
<span className="text-base font-semibold text-gray-900">Genel Toplam:</span>
|
||||
<span className="text-base font-bold text-blue-600">
|
||||
{formatCurrency(formData.totalAmount || 0)}
|
||||
</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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{waybill ? "Güncelle" : "Kaydet"}
|
||||
{waybill ? 'Güncelle' : 'Kaydet'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default WaybillForm;
|
||||
export default WaybillForm
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useState } from 'react'
|
||||
import {
|
||||
FaPlus,
|
||||
FaSearch,
|
||||
|
|
@ -9,28 +9,24 @@ import {
|
|||
FaTruck,
|
||||
FaCheck,
|
||||
FaEye,
|
||||
} from "react-icons/fa";
|
||||
import {
|
||||
FiWaybill,
|
||||
WaybillTypeEnum,
|
||||
WaybillStatusEnum,
|
||||
} from "../../../types/fi";
|
||||
import DataTable, { Column } from "../../../components/common/DataTable";
|
||||
import Widget from "../../../components/common/Widget";
|
||||
} from 'react-icons/fa'
|
||||
import { FiWaybill, WaybillTypeEnum, WaybillStatusEnum } from '../../../types/fi'
|
||||
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||
import Widget from '../../../components/common/Widget'
|
||||
import {
|
||||
getWaybillStatusColor,
|
||||
getWaybillStatusText,
|
||||
getWaybillTypeColor,
|
||||
getWaybillTypeText,
|
||||
} from "../../../utils/erp";
|
||||
} from '../../../utils/erp'
|
||||
|
||||
interface WaybillManagementProps {
|
||||
waybills: FiWaybill[];
|
||||
onAdd: () => void;
|
||||
onEdit: (waybill: FiWaybill) => void;
|
||||
onViewDetails: (waybill: FiWaybill) => void;
|
||||
onCreateInvoice: (waybill: FiWaybill) => void;
|
||||
onMarkAsDelivered: (waybill: FiWaybill) => void;
|
||||
waybills: FiWaybill[]
|
||||
onAdd: () => void
|
||||
onEdit: (waybill: FiWaybill) => void
|
||||
onViewDetails: (waybill: FiWaybill) => void
|
||||
onCreateInvoice: (waybill: FiWaybill) => void
|
||||
onMarkAsDelivered: (waybill: FiWaybill) => void
|
||||
}
|
||||
|
||||
const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||
|
|
@ -41,109 +37,87 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
onCreateInvoice,
|
||||
onMarkAsDelivered,
|
||||
}) => {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [selectedType, setSelectedType] = useState<WaybillTypeEnum | "all">(
|
||||
"all"
|
||||
);
|
||||
const [selectedStatus, setSelectedStatus] = useState<
|
||||
WaybillStatusEnum | "all"
|
||||
>("all");
|
||||
const [showInvoicedOnly, setShowInvoicedOnly] = useState<
|
||||
"all" | "invoiced" | "not_invoiced"
|
||||
>("not_invoiced");
|
||||
const [sortBy, setSortBy] = useState<"date" | "amount" | "deliveryDate">(
|
||||
"date"
|
||||
);
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [selectedType, setSelectedType] = useState<WaybillTypeEnum | 'all'>('all')
|
||||
const [selectedStatus, setSelectedStatus] = useState<WaybillStatusEnum | 'all'>('all')
|
||||
const [showInvoicedOnly, setShowInvoicedOnly] = useState<'all' | 'invoiced' | 'not_invoiced'>(
|
||||
'not_invoiced',
|
||||
)
|
||||
const [sortBy, setSortBy] = useState<'date' | 'amount' | 'deliveryDate'>('date')
|
||||
|
||||
const filteredWaybills = waybills
|
||||
.filter((waybill) => {
|
||||
if (
|
||||
searchTerm &&
|
||||
!waybill.waybillNumber
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()) &&
|
||||
!waybill.currentAccount?.accountCode
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()) &&
|
||||
!waybill.trackingNumber
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase())
|
||||
!waybill.waybillNumber.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) {
|
||||
return false;
|
||||
if (selectedType !== 'all' && waybill.waybillType !== selectedType) {
|
||||
return false
|
||||
}
|
||||
if (selectedStatus !== "all" && waybill.status !== selectedStatus) {
|
||||
return false;
|
||||
if (selectedStatus !== 'all' && waybill.status !== selectedStatus) {
|
||||
return false
|
||||
}
|
||||
if (showInvoicedOnly === "invoiced" && !waybill.isInvoiced) {
|
||||
return false;
|
||||
if (showInvoicedOnly === 'invoiced' && !waybill.isInvoiced) {
|
||||
return false
|
||||
}
|
||||
if (showInvoicedOnly === "not_invoiced" && waybill.isInvoiced) {
|
||||
return false;
|
||||
if (showInvoicedOnly === 'not_invoiced' && waybill.isInvoiced) {
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
})
|
||||
.sort((a, b) => {
|
||||
switch (sortBy) {
|
||||
case "date":
|
||||
return (
|
||||
new Date(b.waybillDate).getTime() -
|
||||
new Date(a.waybillDate).getTime()
|
||||
);
|
||||
case "amount":
|
||||
return b.totalAmount - a.totalAmount;
|
||||
case "deliveryDate":
|
||||
if (!a.deliveryDate && !b.deliveryDate) return 0;
|
||||
if (!a.deliveryDate) return 1;
|
||||
if (!b.deliveryDate) return -1;
|
||||
return (
|
||||
new Date(a.deliveryDate).getTime() -
|
||||
new Date(b.deliveryDate).getTime()
|
||||
);
|
||||
case 'date':
|
||||
return new Date(b.waybillDate).getTime() - new Date(a.waybillDate).getTime()
|
||||
case 'amount':
|
||||
return b.totalAmount - a.totalAmount
|
||||
case 'deliveryDate':
|
||||
if (!a.deliveryDate && !b.deliveryDate) return 0
|
||||
if (!a.deliveryDate) return 1
|
||||
if (!b.deliveryDate) return -1
|
||||
return new Date(a.deliveryDate).getTime() - new Date(b.deliveryDate).getTime()
|
||||
default:
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const formatCurrency = (amount: number) => {
|
||||
return amount.toLocaleString("tr-TR", {
|
||||
style: "currency",
|
||||
currency: "TRY",
|
||||
return amount.toLocaleString('tr-TR', {
|
||||
style: 'currency',
|
||||
currency: 'TRY',
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
const formatDate = (date: Date) => {
|
||||
return new Date(date).toLocaleDateString("tr-TR");
|
||||
};
|
||||
return new Date(date).toLocaleDateString('tr-TR')
|
||||
}
|
||||
|
||||
const columns: Column<FiWaybill>[] = [
|
||||
{
|
||||
key: "waybillNumber",
|
||||
header: "İrsaliye No",
|
||||
key: 'waybillNumber',
|
||||
header: 'İrsaliye No',
|
||||
sortable: true,
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
{waybill.waybillNumber}
|
||||
</div>
|
||||
<div className="font-medium text-gray-900">{waybill.waybillNumber}</div>
|
||||
{waybill.trackingNumber && (
|
||||
<div className="text-sm text-gray-500">
|
||||
Takip: {waybill.trackingNumber}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">Takip: {waybill.trackingNumber}</div>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
header: "Tür",
|
||||
key: 'type',
|
||||
header: 'Tür',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
|
||||
waybill.waybillType
|
||||
waybill.waybillType,
|
||||
)}`}
|
||||
>
|
||||
{getWaybillTypeText(waybill.waybillType)}
|
||||
|
|
@ -151,22 +125,20 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
),
|
||||
},
|
||||
{
|
||||
key: "currentAccount",
|
||||
header: "Cari Hesap",
|
||||
key: 'currentAccount',
|
||||
header: 'Cari Hesap',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
{waybill.currentAccount?.accountCode || "Bilinmeyen"}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
{waybill.currentAccount?.accountCode}
|
||||
{waybill.currentAccount?.accountCode || 'Bilinmeyen'}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">{waybill.currentAccount?.accountCode}</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "dates",
|
||||
header: "Tarihler",
|
||||
key: 'dates',
|
||||
header: 'Tarihler',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div className="text-sm">
|
||||
<div className="flex items-center gap-1">
|
||||
|
|
@ -183,27 +155,23 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
),
|
||||
},
|
||||
{
|
||||
key: "amounts",
|
||||
header: "Tutarlar",
|
||||
key: 'amounts',
|
||||
header: 'Tutarlar',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div className="text-right">
|
||||
<div className="font-medium text-gray-900">
|
||||
{formatCurrency(waybill.totalAmount)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
{waybill.items.length} kalem
|
||||
</div>
|
||||
<div className="font-medium text-gray-900">{formatCurrency(waybill.totalAmount)}</div>
|
||||
<div className="text-sm text-gray-500">{waybill.items.length} kalem</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
header: "Durum",
|
||||
key: 'status',
|
||||
header: 'Durum',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div className="space-y-1">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
|
||||
waybill.status
|
||||
waybill.status,
|
||||
)}`}
|
||||
>
|
||||
{getWaybillStatusText(waybill.status)}
|
||||
|
|
@ -211,25 +179,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
<br />
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${
|
||||
waybill.isInvoiced
|
||||
? "bg-green-100 text-green-800"
|
||||
: "bg-yellow-100 text-yellow-800"
|
||||
waybill.isInvoiced ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
|
||||
}`}
|
||||
>
|
||||
{waybill.isInvoiced ? "Faturalandı" : "Faturalanmadı"}
|
||||
{waybill.isInvoiced ? 'Faturalandı' : 'Faturalanmadı'}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "carrier",
|
||||
header: "Kargo",
|
||||
key: 'carrier',
|
||||
header: 'Kargo',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div className="text-sm">
|
||||
{waybill.carrierCompany && (
|
||||
<div className="font-medium text-gray-900">
|
||||
{waybill.carrierCompany}
|
||||
</div>
|
||||
<div className="font-medium text-gray-900">{waybill.carrierCompany}</div>
|
||||
)}
|
||||
{waybill.receiverName && (
|
||||
<div className="text-gray-500">Alıcı: {waybill.receiverName}</div>
|
||||
|
|
@ -238,8 +202,8 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
),
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
header: "İşlemler",
|
||||
key: 'actions',
|
||||
header: 'İşlemler',
|
||||
render: (waybill: FiWaybill) => (
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
|
|
@ -256,16 +220,15 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
>
|
||||
<FaEdit className="w-4 h-4" />
|
||||
</button>
|
||||
{!waybill.isInvoiced &&
|
||||
waybill.status === WaybillStatusEnum.Delivered && (
|
||||
<button
|
||||
onClick={() => onCreateInvoice(waybill)}
|
||||
className="p-1 text-purple-600 hover:bg-purple-50 rounded"
|
||||
title="Fatura Oluştur"
|
||||
>
|
||||
<FaFileAlt className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
{!waybill.isInvoiced && waybill.status === WaybillStatusEnum.Delivered && (
|
||||
<button
|
||||
onClick={() => onCreateInvoice(waybill)}
|
||||
className="p-1 text-purple-600 hover:bg-purple-50 rounded"
|
||||
title="Fatura Oluştur"
|
||||
>
|
||||
<FaFileAlt className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
{waybill.status === WaybillStatusEnum.Confirmed && (
|
||||
<button
|
||||
onClick={() => onMarkAsDelivered(waybill)}
|
||||
|
|
@ -278,18 +241,13 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
// Calculate statistics
|
||||
const totalWaybills = waybills.length;
|
||||
const notInvoicedWaybills = waybills.filter((w) => !w.isInvoiced);
|
||||
const deliveredWaybills = waybills.filter(
|
||||
(w) => w.status === WaybillStatusEnum.Delivered
|
||||
);
|
||||
const totalNotInvoicedAmount = notInvoicedWaybills.reduce(
|
||||
(sum, w) => sum + w.totalAmount,
|
||||
0
|
||||
);
|
||||
const totalWaybills = waybills.length
|
||||
const notInvoicedWaybills = waybills.filter((w) => !w.isInvoiced)
|
||||
const deliveredWaybills = waybills.filter((w) => w.status === WaybillStatusEnum.Delivered)
|
||||
const totalNotInvoicedAmount = notInvoicedWaybills.reduce((sum, w) => sum + w.totalAmount, 0)
|
||||
|
||||
// Waybill type distribution
|
||||
const typeDistribution = Object.values(WaybillTypeEnum).map((type) => ({
|
||||
|
|
@ -298,16 +256,14 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
amount: waybills
|
||||
.filter((w) => w.waybillType === type)
|
||||
.reduce((sum, w) => sum + w.totalAmount, 0),
|
||||
}));
|
||||
}))
|
||||
|
||||
// Status distribution
|
||||
const statusDistribution = Object.values(WaybillStatusEnum).map((status) => ({
|
||||
status,
|
||||
count: waybills.filter((w) => w.status === status).length,
|
||||
amount: waybills
|
||||
.filter((w) => w.status === status)
|
||||
.reduce((sum, w) => sum + w.totalAmount, 0),
|
||||
}));
|
||||
amount: waybills.filter((w) => w.status === status).reduce((sum, w) => sum + w.totalAmount, 0),
|
||||
}))
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
|
|
@ -315,9 +271,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-gray-900">İrsaliye Yönetimi</h2>
|
||||
<p className="text-gray-600">
|
||||
Giriş ve çıkış irsaliyeleri yönetimi
|
||||
</p>
|
||||
<p className="text-gray-600">Giriş ve çıkış irsaliyeleri yönetimi</p>
|
||||
</div>
|
||||
<div className="flex gap-2 text-sm">
|
||||
<button
|
||||
|
|
@ -332,12 +286,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<Widget
|
||||
title="Toplam İrsaliye"
|
||||
value={totalWaybills}
|
||||
color="blue"
|
||||
icon="FaFileAlt"
|
||||
/>
|
||||
<Widget title="Toplam İrsaliye" value={totalWaybills} color="blue" icon="FaFileAlt" />
|
||||
|
||||
<Widget
|
||||
title="Faturalanmamış"
|
||||
|
|
@ -364,25 +313,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
{/* Distribution Charts */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
İrsaliye Türü Dağılımı
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">İrsaliye Türü Dağılımı</h3>
|
||||
<div className="space-y-2">
|
||||
{typeDistribution.map(({ type, count, amount }) => (
|
||||
<div key={type} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
|
||||
type
|
||||
type,
|
||||
)}`}
|
||||
>
|
||||
{getWaybillTypeText(type)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-gray-600">
|
||||
{count} irsaliye
|
||||
</span>
|
||||
<span className="text-sm text-gray-600">{count} irsaliye</span>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{formatCurrency(amount)}
|
||||
</span>
|
||||
|
|
@ -393,25 +338,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
||||
Durum Dağılımı
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-gray-900 mb-3">Durum Dağılımı</h3>
|
||||
<div className="space-y-2">
|
||||
{statusDistribution.map(({ status, count, amount }) => (
|
||||
<div key={status} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
|
||||
status
|
||||
status,
|
||||
)}`}
|
||||
>
|
||||
{getWaybillStatusText(status)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-gray-600">
|
||||
{count} irsaliye
|
||||
</span>
|
||||
<span className="text-sm text-gray-600">{count} irsaliye</span>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{formatCurrency(amount)}
|
||||
</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="flex items-center gap-2">
|
||||
<FaExclamationTriangle className="w-5 h-5 text-orange-600" />
|
||||
<h3 className="text-base font-semibold text-orange-900">
|
||||
Faturalanmamış İrsaliyeler
|
||||
</h3>
|
||||
<h3 className="text-base font-semibold text-orange-900">Faturalanmamış İrsaliyeler</h3>
|
||||
</div>
|
||||
<p className="text-sm text-orange-700 mt-1">
|
||||
{notInvoicedWaybills.length} adet irsaliye henüz faturalanmamış.
|
||||
Toplam tutar: {formatCurrency(totalNotInvoicedAmount)}
|
||||
{notInvoicedWaybills.length} adet irsaliye henüz faturalanmamış. Toplam tutar:{' '}
|
||||
{formatCurrency(totalNotInvoicedAmount)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -453,9 +392,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={selectedType}
|
||||
onChange={(e) =>
|
||||
setSelectedType(e.target.value as WaybillTypeEnum | "all")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="all">Tüm Türler</option>
|
||||
|
|
@ -468,9 +405,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={selectedStatus}
|
||||
onChange={(e) =>
|
||||
setSelectedStatus(e.target.value as WaybillStatusEnum | "all")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
|
|
@ -484,9 +419,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
<select
|
||||
value={showInvoicedOnly}
|
||||
onChange={(e) =>
|
||||
setShowInvoicedOnly(
|
||||
e.target.value as "all" | "invoiced" | "not_invoiced"
|
||||
)
|
||||
setShowInvoicedOnly(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"
|
||||
>
|
||||
|
|
@ -497,9 +430,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
|
||||
<select
|
||||
value={sortBy}
|
||||
onChange={(e) =>
|
||||
setSortBy(e.target.value as "date" | "amount" | "deliveryDate")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="date">Tarihe Göre</option>
|
||||
|
|
@ -516,16 +447,14 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
|||
{filteredWaybills.length === 0 && (
|
||||
<div className="text-center py-10">
|
||||
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
|
||||
<h3 className="text-base font-medium text-gray-900 mb-2">
|
||||
İrsaliye bulunamadı
|
||||
</h3>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-2">İrsaliye bulunamadı</h3>
|
||||
<p className="text-sm text-gray-500">
|
||||
Yeni bir irsaliye ekleyin veya arama kriterlerinizi değiştirin.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default WaybillManagement;
|
||||
export default WaybillManagement
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ import Widget from '../../../components/common/Widget'
|
|||
import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
|
||||
import {
|
||||
getBusinessPartyStatusColor,
|
||||
getBusinessPartyStatusName,
|
||||
getCustomerSegmentName,
|
||||
getBusinessPartyStatusText,
|
||||
getCustomerSegmentText,
|
||||
} from '../../../utils/erp'
|
||||
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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option>
|
||||
<option value={BusinessPartyStatusEnum.Active}>Aktif</option>
|
||||
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option>
|
||||
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option>
|
||||
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getBusinessPartyStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option>
|
||||
<option value={CustomerSegmentEnum.SMB}>KOBİ</option>
|
||||
<option value={CustomerSegmentEnum.Startup}>Girişim</option>
|
||||
<option value={CustomerSegmentEnum.Government}>Kamu</option>
|
||||
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||
<option key={segment} value={segment}>
|
||||
{getCustomerSegmentText(segment)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -289,7 +291,7 @@ const CustomerCards: React.FC = () => {
|
|||
{customer.code}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600">
|
||||
{getCustomerSegmentName(customer.customerSegment!)}
|
||||
{getCustomerSegmentText(customer.customerSegment!)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -299,7 +301,7 @@ const CustomerCards: React.FC = () => {
|
|||
getBusinessPartyStatusColor(customer.status!),
|
||||
)}
|
||||
>
|
||||
{getBusinessPartyStatusName(customer.status!)}
|
||||
{getBusinessPartyStatusText(customer.status!)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,13 @@ import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBu
|
|||
import { BusinessParty, BusinessPartyStatusEnum, PaymentTerms } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
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 { id } = useParams<{ id: string }>()
|
||||
|
|
@ -316,10 +323,11 @@ const CustomerEdit: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={CustomerTypeEnum.Company}>Şirket</option>
|
||||
<option value={CustomerTypeEnum.Individual}>Bireysel</option>
|
||||
<option value={CustomerTypeEnum.Government}>Kamu</option>
|
||||
<option value={CustomerTypeEnum.NonProfit}>Kar Amacı Gütmeyen</option>
|
||||
{Object.values(CustomerTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getCustomerTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -354,10 +362,11 @@ const CustomerEdit: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option>
|
||||
<option value={BusinessPartyStatusEnum.Active}>Aktif</option>
|
||||
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option>
|
||||
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option>
|
||||
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getBusinessPartyStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -370,10 +379,11 @@ const CustomerEdit: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option>
|
||||
<option value={CustomerSegmentEnum.SMB}>KOBİ</option>
|
||||
<option value={CustomerSegmentEnum.Startup}>Girişim</option>
|
||||
<option value={CustomerSegmentEnum.Government}>Kamu</option>
|
||||
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||
<option key={segment} value={segment}>
|
||||
{getCustomerSegmentText(segment)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -644,10 +654,11 @@ const CustomerEdit: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">Türk Lirası (TRY)</option>
|
||||
<option value="USD">Amerikan Doları (USD)</option>
|
||||
<option value="EUR">Euro (EUR)</option>
|
||||
<option value="GBP">İngiliz Sterlini (GBP)</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -660,11 +671,11 @@ const CustomerEdit: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={PaymentTerms.Prepaid}>Peşin</option>
|
||||
<option value={PaymentTerms.COD}>Kapıda Ödeme</option>
|
||||
<option value={PaymentTerms.Net30}>30 Gün Vade</option>
|
||||
<option value={PaymentTerms.Net60}>60 Gün Vade</option>
|
||||
<option value={PaymentTerms.Net90}>90 Gün Vade</option>
|
||||
{Object.values(PaymentTerms).map((term) => (
|
||||
<option key={term} value={term}>
|
||||
{getPaymentTermsText(term)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,9 +11,23 @@ import {
|
|||
} from 'react-icons/fa'
|
||||
import LoadingSpinner from '../../../components/common/LoadingSpinner'
|
||||
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 { 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 {
|
||||
[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"
|
||||
>
|
||||
<option value="COMPANY">Şirket</option>
|
||||
<option value="INDIVIDUAL">Bireysel</option>
|
||||
{Object.values(CustomerTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getCustomerTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Sektör seçin</option>
|
||||
<option value="TECHNOLOGY">Teknoloji</option>
|
||||
<option value="MANUFACTURING">İmalat</option>
|
||||
<option value="CONSTRUCTION">İnşaat</option>
|
||||
<option value="AUTOMOTIVE">Otomotiv</option>
|
||||
<option value="RETAIL">Perakende</option>
|
||||
<option value="FINANCE">Finans</option>
|
||||
<option value="HEALTHCARE">Sağlık</option>
|
||||
<option value="OTHER">Diğer</option>
|
||||
{Object.values(BusinessPartyIndustryEnum).map((industry) => (
|
||||
<option key={industry} value={industry}>
|
||||
{getBusinessPartyIndustryText(industry)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -369,11 +383,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="CASH">Peşin</option>
|
||||
<option value="NET_15">15 Gün Vadeli</option>
|
||||
<option value="NET_30">30 Gün Vadeli</option>
|
||||
<option value="NET_60">60 Gün Vadeli</option>
|
||||
<option value="NET_90">90 Gün Vadeli</option>
|
||||
{Object.values(PaymentTerms).map((term) => (
|
||||
<option key={term} value={term}>
|
||||
{getPaymentTermsText(term)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -386,9 +400,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">Türk Lirası (TRY)</option>
|
||||
<option value="USD">Amerikan Doları (USD)</option>
|
||||
<option value="EUR">Euro (EUR)</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -415,10 +431,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="ACTIVE">Aktif</option>
|
||||
<option value="INACTIVE">Pasif</option>
|
||||
<option value="PROSPECT">Potansiyel</option>
|
||||
<option value="BLOCKED">Blokeli</option>
|
||||
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getBusinessPartyStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -431,10 +448,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="STANDARD">Standart</option>
|
||||
<option value="PREMIUM">Premium</option>
|
||||
<option value="ENTERPRISE">Kurumsal</option>
|
||||
<option value="VIP">VIP</option>
|
||||
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||
<option key={segment} value={segment}>
|
||||
{getCustomerSegmentText(segment)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -442,16 +460,13 @@ const CustomerForm: React.FC = () => {
|
|||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Sorumlu Satış Temsilcisi
|
||||
</label>
|
||||
<select
|
||||
<input
|
||||
type="text"
|
||||
value={formData.assignedSalesRep}
|
||||
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"
|
||||
>
|
||||
<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>
|
||||
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ı"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,24 @@ import {
|
|||
FaEnvelope,
|
||||
} from 'react-icons/fa'
|
||||
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 { Container } from '@/components/shared'
|
||||
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 {
|
||||
[key: string]: string
|
||||
|
|
@ -174,13 +188,14 @@ const CustomerForm: React.FC = () => {
|
|||
</label>
|
||||
<select
|
||||
value={formData.customerType}
|
||||
onChange={(e) =>
|
||||
handleInputChange('customerType', e.target.value as 'INDIVIDUAL' | 'COMPANY')
|
||||
}
|
||||
onChange={(e) => handleInputChange('customerType', 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"
|
||||
>
|
||||
<option value="COMPANY">Şirket</option>
|
||||
<option value="INDIVIDUAL">Bireysel</option>
|
||||
{Object.values(CustomerTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getCustomerTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Sektör seçin</option>
|
||||
<option value="TECHNOLOGY">Teknoloji</option>
|
||||
<option value="MANUFACTURING">İmalat</option>
|
||||
<option value="CONSTRUCTION">İnşaat</option>
|
||||
<option value="AUTOMOTIVE">Otomotiv</option>
|
||||
<option value="RETAIL">Perakende</option>
|
||||
<option value="FINANCE">Finans</option>
|
||||
<option value="HEALTHCARE">Sağlık</option>
|
||||
<option value="OTHER">Diğer</option>
|
||||
{Object.values(BusinessPartyIndustryEnum).map((industry) => (
|
||||
<option key={industry} value={industry}>
|
||||
{getBusinessPartyIndustryText(industry)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -367,11 +379,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="CASH">Peşin</option>
|
||||
<option value="NET_15">15 Gün Vadeli</option>
|
||||
<option value="NET_30">30 Gün Vadeli</option>
|
||||
<option value="NET_60">60 Gün Vadeli</option>
|
||||
<option value="NET_90">90 Gün Vadeli</option>
|
||||
{Object.values(PaymentTerms).map((term) => (
|
||||
<option key={term} value={term}>
|
||||
{getPaymentTermsText(term)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -384,9 +396,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">Türk Lirası (TRY)</option>
|
||||
<option value="USD">Amerikan Doları (USD)</option>
|
||||
<option value="EUR">Euro (EUR)</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -413,10 +427,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="ACTIVE">Aktif</option>
|
||||
<option value="INACTIVE">Pasif</option>
|
||||
<option value="PROSPECT">Potansiyel</option>
|
||||
<option value="BLOCKED">Blokeli</option>
|
||||
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getBusinessPartyStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -429,10 +444,11 @@ const CustomerForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="STANDARD">Standart</option>
|
||||
<option value="PREMIUM">Premium</option>
|
||||
<option value="ENTERPRISE">Kurumsal</option>
|
||||
<option value="VIP">VIP</option>
|
||||
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||
<option key={segment} value={segment}>
|
||||
{getCustomerSegmentText(segment)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -440,16 +456,13 @@ const CustomerForm: React.FC = () => {
|
|||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Sorumlu Satış Temsilcisi
|
||||
</label>
|
||||
<select
|
||||
<input
|
||||
type="text"
|
||||
value={formData.assignedSalesRep}
|
||||
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"
|
||||
>
|
||||
<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>
|
||||
placeholder="Satış temsilcisi adı"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
|
|||
import Widget from '../../../components/common/Widget'
|
||||
import {
|
||||
getBusinessPartyStatusColor,
|
||||
getBusinessPartyStatusName,
|
||||
getBusinessPartyStatusText,
|
||||
getCustomerSegmentColor,
|
||||
getCustomerSegmentName,
|
||||
getCustomerSegmentText,
|
||||
} from '../../../utils/erp'
|
||||
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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option>
|
||||
<option value={BusinessPartyStatusEnum.Active}>Aktif</option>
|
||||
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option>
|
||||
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option>
|
||||
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getBusinessPartyStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option>
|
||||
<option value={CustomerSegmentEnum.SMB}>KOBİ</option>
|
||||
<option value={CustomerSegmentEnum.Startup}>Girişim</option>
|
||||
<option value={CustomerSegmentEnum.Government}>Kamu</option>
|
||||
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||
<option key={segment} value={segment}>
|
||||
{getCustomerSegmentText(segment)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -310,7 +312,7 @@ const CustomerList: React.FC = () => {
|
|||
),
|
||||
)}
|
||||
>
|
||||
{getCustomerSegmentName(
|
||||
{getCustomerSegmentText(
|
||||
customer.customerSegment || CustomerSegmentEnum.SMB,
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -322,7 +324,7 @@ const CustomerList: React.FC = () => {
|
|||
),
|
||||
)}
|
||||
>
|
||||
{getBusinessPartyStatusName(
|
||||
{getBusinessPartyStatusText(
|
||||
customer.status ?? BusinessPartyStatusEnum.Prospect,
|
||||
)}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import dayjs from 'dayjs'
|
|||
import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
||||
import {
|
||||
getBusinessPartyStatusColor,
|
||||
getBusinessPartyStatusName,
|
||||
getCustomerSegmentName,
|
||||
getBusinessPartyStatusText,
|
||||
getCustomerSegmentText,
|
||||
} from '../../../utils/erp'
|
||||
import { BusinessPartyStatusEnum } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
|
|
@ -167,7 +167,7 @@ const CustomerView: React.FC = () => {
|
|||
),
|
||||
)}
|
||||
>
|
||||
{getBusinessPartyStatusName(
|
||||
{getBusinessPartyStatusText(
|
||||
customer.status || BusinessPartyStatusEnum.Active,
|
||||
)}
|
||||
</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-400">•</span>
|
||||
<span className="text-sm text-gray-600">
|
||||
{getCustomerSegmentName(
|
||||
{getCustomerSegmentText(
|
||||
customer.customerSegment || CustomerSegmentEnum.Startup,
|
||||
)}
|
||||
</span>
|
||||
|
|
@ -311,7 +311,7 @@ const CustomerView: React.FC = () => {
|
|||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Segment:</span>
|
||||
<span className="font-medium">
|
||||
{getCustomerSegmentName(
|
||||
{getCustomerSegmentText(
|
||||
customer.customerSegment || CustomerSegmentEnum.Startup,
|
||||
)}
|
||||
</span>
|
||||
|
|
@ -729,7 +729,7 @@ const CustomerView: React.FC = () => {
|
|||
),
|
||||
)}
|
||||
>
|
||||
{getBusinessPartyStatusName(
|
||||
{getBusinessPartyStatusText(
|
||||
customer.status || BusinessPartyStatusEnum.Active,
|
||||
)}
|
||||
</span>
|
||||
|
|
@ -739,7 +739,7 @@ const CustomerView: React.FC = () => {
|
|||
Müşteri Segmenti
|
||||
</label>
|
||||
<p className="text-gray-900">
|
||||
{getCustomerSegmentName(
|
||||
{getCustomerSegmentText(
|
||||
customer.customerSegment || CustomerSegmentEnum.Startup,
|
||||
)}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
|||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { BusinessParty } from '../../../types/common'
|
||||
import { getOpportunityLeadSourceText, getOpportunityStageText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface OpportunityFormProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -353,9 +354,11 @@ const OpportunityForm: React.FC<OpportunityFormProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value="TRY">TRY - Türk Lirası</option>
|
||||
<option value="USD">USD - Amerikan Doları</option>
|
||||
<option value="EUR">EUR - Euro</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import { mockSalesOrders } from '../../../mocks/mockSalesOrders'
|
|||
import { BusinessParty, PaymentTerms } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { getPaymentTermsText, getSaleOrderStatusText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
const SalesOrderForm: React.FC = () => {
|
||||
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"
|
||||
>
|
||||
<option value={SaleOrderStatusEnum.Draft}>Taslak</option>
|
||||
<option value={SaleOrderStatusEnum.Confirmed}>Onaylandı</option>
|
||||
<option value={SaleOrderStatusEnum.InProduction}>Üretimde</option>
|
||||
<option value={SaleOrderStatusEnum.Ready}>Hazır</option>
|
||||
<option value={SaleOrderStatusEnum.Shipped}>Kargoda</option>
|
||||
<option value={SaleOrderStatusEnum.Delivered}>Teslim Edildi</option>
|
||||
<option value={SaleOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(SaleOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getSaleOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -684,9 +684,11 @@ const SalesOrderForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">TRY - Türk Lirası</option>
|
||||
<option value="USD">USD - ABD Doları</option>
|
||||
<option value="EUR">EUR - Euro</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Seçin...</option>
|
||||
<option value="NET30">30 Gün Vadeli</option>
|
||||
<option value="NET60">60 Gün Vadeli</option>
|
||||
<option value="NET90">90 Gün Vadeli</option>
|
||||
<option value="COD">Kapıda Ödeme</option>
|
||||
<option value="PREPAID">Peşin</option>
|
||||
{Object.values(PaymentTerms).map((term) => (
|
||||
<option key={term} value={term}>
|
||||
{getPaymentTermsText(term)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
|
|||
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { getTeamRoleText } from '@/utils/erp'
|
||||
|
||||
const SalesTeamCreate: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
|
|
@ -308,9 +309,11 @@ const SalesTeamCreate: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
||||
<option value={TeamRoleEnum.Lead}>Takım Lideri</option>
|
||||
<option value={TeamRoleEnum.Manager}>Yönetici</option>
|
||||
{Object.values(TeamRoleEnum).map((role) => (
|
||||
<option key={role} value={role}>
|
||||
{getTeamRoleText(role)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
|
|||
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { getTeamRoleText } from '@/utils/erp'
|
||||
|
||||
const SalesTeamEdit: React.FC = () => {
|
||||
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"
|
||||
>
|
||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
||||
<option value={TeamRoleEnum.Lead}>Takım Lideri</option>
|
||||
<option value={TeamRoleEnum.Manager}>Yönetici</option>
|
||||
{Object.values(TeamRoleEnum).map((role) => (
|
||||
<option key={role} value={role}>
|
||||
{getTeamRoleText(role)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ export function ForumView({
|
|||
: 'hover:text-blue-600 cursor-pointer'
|
||||
}`}
|
||||
>
|
||||
Forum
|
||||
<h2 className="text-2xl font-bold text-gray-900">Forum</h2>
|
||||
</button>
|
||||
{selectedCategory && (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaSave, FaTimes } from "react-icons/fa";
|
||||
import { HrCostCenter, CostCenterType } from "../../../types/hr";
|
||||
import { mockEmployees } from "../../../mocks/mockEmployees";
|
||||
import { mockCostCenters } from "../../../mocks/mockCostCenters";
|
||||
import { getCostCenterTypeText } from "../../../utils/erp";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaSave, FaTimes } from 'react-icons/fa'
|
||||
import { HrCostCenter, CostCenterType } from '../../../types/hr'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { mockCostCenters } from '../../../mocks/mockCostCenters'
|
||||
import { getCostCenterTypeText } from '../../../utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface CostCenterFormModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (costCenter: Partial<HrCostCenter>) => void;
|
||||
costCenter?: HrCostCenter;
|
||||
title: string;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (costCenter: Partial<HrCostCenter>) => void
|
||||
costCenter?: HrCostCenter
|
||||
title: string
|
||||
}
|
||||
|
||||
const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||
|
|
@ -21,55 +22,55 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
title,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState({
|
||||
costCenterCode: "",
|
||||
name: "",
|
||||
description: "",
|
||||
costCenterCode: '',
|
||||
name: '',
|
||||
description: '',
|
||||
costCenterType: CostCenterType.Standard,
|
||||
responsibleEmployeeId: "",
|
||||
parentCostCenterId: "",
|
||||
responsibleEmployeeId: '',
|
||||
parentCostCenterId: '',
|
||||
budgetedAmount: 0,
|
||||
actualAmount: 0,
|
||||
currency: "TRY",
|
||||
fiscalYear: "2025",
|
||||
currency: 'TRY',
|
||||
fiscalYear: '2025',
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (costCenter) {
|
||||
setFormData({
|
||||
costCenterCode: costCenter.code,
|
||||
name: costCenter.name,
|
||||
description: costCenter.description || "",
|
||||
description: costCenter.description || '',
|
||||
costCenterType: costCenter.costCenterType,
|
||||
responsibleEmployeeId: costCenter.responsibleEmployeeId || "",
|
||||
parentCostCenterId: costCenter.parentCostCenterId || "",
|
||||
responsibleEmployeeId: costCenter.responsibleEmployeeId || '',
|
||||
parentCostCenterId: costCenter.parentCostCenterId || '',
|
||||
budgetedAmount: costCenter.budgetedAmount,
|
||||
actualAmount: costCenter.actualAmount,
|
||||
currency: costCenter.currency,
|
||||
fiscalYear: costCenter.fiscalYear,
|
||||
isActive: costCenter.isActive,
|
||||
});
|
||||
})
|
||||
} else {
|
||||
setFormData({
|
||||
costCenterCode: "",
|
||||
name: "",
|
||||
description: "",
|
||||
costCenterCode: '',
|
||||
name: '',
|
||||
description: '',
|
||||
costCenterType: CostCenterType.Standard,
|
||||
responsibleEmployeeId: "",
|
||||
parentCostCenterId: "",
|
||||
responsibleEmployeeId: '',
|
||||
parentCostCenterId: '',
|
||||
budgetedAmount: 0,
|
||||
actualAmount: 0,
|
||||
currency: "TRY",
|
||||
fiscalYear: "2025",
|
||||
currency: 'TRY',
|
||||
fiscalYear: '2025',
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
}
|
||||
}, [costCenter]);
|
||||
}, [costCenter])
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
onSave(formData);
|
||||
};
|
||||
e.preventDefault()
|
||||
onSave(formData)
|
||||
}
|
||||
|
||||
return (
|
||||
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="flex items-center justify-between mb-3">
|
||||
<h2 className="text-base font-bold text-gray-900">{title}</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -94,9 +92,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={formData.costCenterCode}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, costCenterCode: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
required
|
||||
/>
|
||||
|
|
@ -109,9 +105,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={formData.name}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, name: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
required
|
||||
/>
|
||||
|
|
@ -119,14 +113,10 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Açıklama
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Açıklama</label>
|
||||
<textarea
|
||||
value={formData.description}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, description: e.target.value })
|
||||
}
|
||||
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||
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"
|
||||
/>
|
||||
|
|
@ -206,15 +196,11 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Mali Yıl
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Mali Yıl</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.fiscalYear}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, fiscalYear: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -222,9 +208,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Bütçe Tutarı
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Bütçe Tutarı</label>
|
||||
<input
|
||||
type="number"
|
||||
value={formData.budgetedAmount}
|
||||
|
|
@ -256,19 +240,17 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Para Birimi
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||
<select
|
||||
value={formData.currency}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, currency: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -277,9 +259,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
<input
|
||||
type="checkbox"
|
||||
checked={formData.isActive}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, isActive: e.target.checked })
|
||||
}
|
||||
onChange={(e) => setFormData({ ...formData, isActive: e.target.checked })}
|
||||
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>
|
||||
|
|
@ -305,7 +285,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CostCenterFormModal;
|
||||
export default CostCenterFormModal
|
||||
|
|
|
|||
|
|
@ -808,9 +808,11 @@ const Degree360Evaluation: React.FC = () => {
|
|||
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={CampaignStatusEnum.Draft}>Taslak</option>
|
||||
<option value={CampaignStatusEnum.Active}>Aktif</option>
|
||||
<option value={CampaignStatusEnum.Completed}>Tamamlandı</option>
|
||||
{Object.values(CampaignStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getCampaignStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
|
|
@ -834,7 +836,7 @@ const Degree360Evaluation: React.FC = () => {
|
|||
<option value="all">Tüm Personel</option>
|
||||
{mockEmployees.map((employee) => (
|
||||
<option key={employee.id} value={employee.id}>
|
||||
{employee.firstName} {employee.lastName}
|
||||
{employee.fullName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
|
@ -887,11 +889,11 @@ const Degree360Evaluation: React.FC = () => {
|
|||
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={ParticipantStatusEnum.Invited}>Davet Edildi</option>
|
||||
<option value={ParticipantStatusEnum.Started}>Başladı</option>
|
||||
<option value={ParticipantStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={ParticipantStatusEnum.Expired}>Süresi Dolmuş</option>
|
||||
<option value={ParticipantStatusEnum.Declined}>Reddedildi</option>
|
||||
{Object.values(ParticipantStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getParticipantStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
QuestionTypeEnum,
|
||||
HrQuestionOption,
|
||||
AssessorTypeEnum,
|
||||
getQuestionTypeText,
|
||||
} from '../../../types/hr'
|
||||
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||
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"
|
||||
>
|
||||
<option value={QuestionTypeEnum.Rating}>Puanlama</option>
|
||||
<option value={QuestionTypeEnum.MultipleChoice}>Çoktan Seçmeli</option>
|
||||
<option value={QuestionTypeEnum.Text}>Metin</option>
|
||||
<option value={QuestionTypeEnum.YesNo}>Evet/Hayır</option>
|
||||
{Object.values(QuestionTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getQuestionTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={EmployeeStatusEnum.Active}>Aktif</option>
|
||||
<option value={EmployeeStatusEnum.Inactive}>Pasif</option>
|
||||
<option value={EmployeeStatusEnum.OnLeave}>İzinli</option>
|
||||
<option value={EmployeeStatusEnum.Suspended}>Askıda</option>
|
||||
<option value={EmployeeStatusEnum.Terminated}>İşten Çıkarılmış</option>
|
||||
{Object.values(EmployeeStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getEmployeeStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ import {
|
|||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { Container } from '@/components/shared'
|
||||
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 {
|
||||
[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"
|
||||
>
|
||||
<option value="">Cinsiyet seçin</option>
|
||||
<option value="MALE">Erkek</option>
|
||||
<option value="FEMALE">Kadın</option>
|
||||
{Object.values(GenderEnum).map((gender) => (
|
||||
<option key={gender} value={gender}>
|
||||
{getGenderText(gender)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Medeni durum seçin</option>
|
||||
<option value="SINGLE">Bekar</option>
|
||||
<option value="MARRIED">Evli</option>
|
||||
<option value="DIVORCED">Boşanmış</option>
|
||||
<option value="WIDOWED">Dul</option>
|
||||
{Object.values(MaritalStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getMaritalStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -508,11 +521,11 @@ const EmployeeForm: React.FC = () => {
|
|||
}`}
|
||||
>
|
||||
<option value="">Tip seçin</option>
|
||||
<option value="FULL_TIME">Tam Zamanlı</option>
|
||||
<option value="PART_TIME">Yarı Zamanlı</option>
|
||||
<option value="CONTRACT">Sözleşmeli</option>
|
||||
<option value="INTERN">Stajyer</option>
|
||||
<option value="TEMPORARY">Geçici</option>
|
||||
{Object.values(EmploymentTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getEmploymentTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.employmentType && (
|
||||
<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)}
|
||||
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>
|
||||
<option value="USD">Amerikan Doları (USD)</option>
|
||||
<option value="EUR">Euro (EUR)</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Grup seçin</option>
|
||||
<option value="MONTHLY">Aylık</option>
|
||||
<option value="WEEKLY">Haftalık</option>
|
||||
<option value="HOURLY">Saatlik</option>
|
||||
<option value={FrequencyUnitEnum.Weeks}>
|
||||
{getFrequencyUnitText(FrequencyUnitEnum.Weeks)}
|
||||
</option>
|
||||
<option value={FrequencyUnitEnum.Months}>
|
||||
{getFrequencyUnitText(FrequencyUnitEnum.Months)}
|
||||
</option>
|
||||
<option value={FrequencyUnitEnum.Hours}>
|
||||
{getFrequencyUnitText(FrequencyUnitEnum.Hours)}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -748,10 +769,11 @@ const EmployeeForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="ACTIVE">Aktif</option>
|
||||
<option value="INACTIVE">Pasif</option>
|
||||
<option value="ON_LEAVE">İzinli</option>
|
||||
<option value="TERMINATED">İşten Ayrılmış</option>
|
||||
{Object.values(EmployeeStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getEmployeeStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@ import {
|
|||
} from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { mockDepartments } from '@/mocks/mockDepartments'
|
||||
|
||||
const EmployeeList: React.FC = () => {
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [filterStatus, setFilterStatus] = useState('all')
|
||||
const [filterDepartment, setFilterDepartment] = useState('all')
|
||||
const [filterDepartment, setFilterDepartment] = useState('')
|
||||
const [showFilters, setShowFilters] = useState(false)
|
||||
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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={EmployeeStatusEnum.Active}>Aktif</option>
|
||||
<option value={EmployeeStatusEnum.Inactive}>Pasif</option>
|
||||
<option value={EmployeeStatusEnum.OnLeave}>İzinli</option>
|
||||
<option value={EmployeeStatusEnum.Suspended}>Askıda</option>
|
||||
<option value={EmployeeStatusEnum.Terminated}>İşten Çıkarıldı</option>
|
||||
{Object.values(EmployeeStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getEmployeeStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value="IT">Bilgi İşlem</option>
|
||||
<option value="PROC">Satınalma</option>
|
||||
<option value="PROD">Üretim</option>
|
||||
<option value="HR">İnsan Kaynakları</option>
|
||||
{mockDepartments.map((dept) => (
|
||||
<option key={dept.id} value={dept.id}>
|
||||
{dept.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaSave, FaTimes, FaPlus, FaTrash } from "react-icons/fa";
|
||||
import { HrJobPosition, JobLevelEnum } from "../../../types/hr";
|
||||
import { mockDepartments } from "../../../mocks/mockDepartments";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaSave, FaTimes, FaPlus, FaTrash } from 'react-icons/fa'
|
||||
import { HrJobPosition, JobLevelEnum } from '../../../types/hr'
|
||||
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||
import { getJobLevelText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
interface JobPositionFormModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (position: Partial<HrJobPosition>) => void;
|
||||
position?: HrJobPosition;
|
||||
title: string;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (position: Partial<HrJobPosition>) => void
|
||||
position?: HrJobPosition
|
||||
title: string
|
||||
}
|
||||
|
||||
const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||
|
|
@ -19,31 +21,31 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
title,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState({
|
||||
positionCode: "",
|
||||
title: "",
|
||||
description: "",
|
||||
departmentId: "",
|
||||
positionCode: '',
|
||||
title: '',
|
||||
description: '',
|
||||
departmentId: '',
|
||||
level: JobLevelEnum.Entry,
|
||||
minSalary: 0,
|
||||
maxSalary: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
requiredSkills: [] as string[],
|
||||
responsibilities: [] as string[],
|
||||
qualifications: [] as string[],
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
const [skillInput, setSkillInput] = useState("");
|
||||
const [responsibilityInput, setResponsibilityInput] = useState("");
|
||||
const [qualificationInput, setQualificationInput] = useState("");
|
||||
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||
const [skillInput, setSkillInput] = useState('')
|
||||
const [responsibilityInput, setResponsibilityInput] = useState('')
|
||||
const [qualificationInput, setQualificationInput] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (position) {
|
||||
setFormData({
|
||||
positionCode: position.code,
|
||||
title: position.name,
|
||||
description: position.description || "",
|
||||
description: position.description || '',
|
||||
departmentId: position.departmentId,
|
||||
level: position.level,
|
||||
minSalary: position.minSalary,
|
||||
|
|
@ -53,97 +55,91 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
responsibilities: [...(position.responsibilities || [])],
|
||||
qualifications: [...(position.qualifications || [])],
|
||||
isActive: position.isActive,
|
||||
});
|
||||
})
|
||||
} else {
|
||||
setFormData({
|
||||
positionCode: "",
|
||||
title: "",
|
||||
description: "",
|
||||
departmentId: "",
|
||||
positionCode: '',
|
||||
title: '',
|
||||
description: '',
|
||||
departmentId: '',
|
||||
level: JobLevelEnum.Entry,
|
||||
minSalary: 0,
|
||||
maxSalary: 0,
|
||||
currency: "TRY",
|
||||
currency: 'TRY',
|
||||
requiredSkills: [],
|
||||
responsibilities: [],
|
||||
qualifications: [],
|
||||
isActive: true,
|
||||
});
|
||||
})
|
||||
}
|
||||
setErrors({});
|
||||
setSkillInput("");
|
||||
setResponsibilityInput("");
|
||||
setQualificationInput("");
|
||||
}, [position, isOpen]);
|
||||
setErrors({})
|
||||
setSkillInput('')
|
||||
setResponsibilityInput('')
|
||||
setQualificationInput('')
|
||||
}, [position, isOpen])
|
||||
|
||||
const validateForm = (): boolean => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
const newErrors: Record<string, string> = {}
|
||||
|
||||
if (!formData.positionCode.trim()) {
|
||||
newErrors.positionCode = "Pozisyon kodu zorunludur";
|
||||
newErrors.positionCode = 'Pozisyon kodu zorunludur'
|
||||
}
|
||||
|
||||
if (!formData.title.trim()) {
|
||||
newErrors.title = "Pozisyon adı zorunludur";
|
||||
newErrors.title = 'Pozisyon adı zorunludur'
|
||||
}
|
||||
|
||||
if (!formData.departmentId) {
|
||||
newErrors.departmentId = "Departman seçimi zorunludur";
|
||||
newErrors.departmentId = 'Departman seçimi zorunludur'
|
||||
}
|
||||
|
||||
if (formData.minSalary < 0) {
|
||||
newErrors.minSalary = "Minimum maaş negatif olamaz";
|
||||
newErrors.minSalary = 'Minimum maaş negatif olamaz'
|
||||
}
|
||||
|
||||
if (formData.maxSalary < 0) {
|
||||
newErrors.maxSalary = "Maksimum maaş negatif olamaz";
|
||||
newErrors.maxSalary = 'Maksimum maaş negatif olamaz'
|
||||
}
|
||||
|
||||
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);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
if (validateForm()) {
|
||||
onSave(formData);
|
||||
onClose();
|
||||
onSave(formData)
|
||||
onClose()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleInputChange = (
|
||||
field: string,
|
||||
value: string | number | boolean | JobLevelEnum
|
||||
) => {
|
||||
const handleInputChange = (field: string, value: string | number | boolean | JobLevelEnum) => {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[field]: value,
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const addSkill = () => {
|
||||
if (
|
||||
skillInput.trim() &&
|
||||
!formData.requiredSkills.includes(skillInput.trim())
|
||||
) {
|
||||
if (skillInput.trim() && !formData.requiredSkills.includes(skillInput.trim())) {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
requiredSkills: [...prev.requiredSkills, skillInput.trim()],
|
||||
}));
|
||||
setSkillInput("");
|
||||
}))
|
||||
setSkillInput('')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const removeSkill = (index: number) => {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
requiredSkills: prev.requiredSkills.filter((_, i) => i !== index),
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const addResponsibility = () => {
|
||||
if (
|
||||
|
|
@ -152,53 +148,44 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
) {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
responsibilities: [
|
||||
...prev.responsibilities,
|
||||
responsibilityInput.trim(),
|
||||
],
|
||||
}));
|
||||
setResponsibilityInput("");
|
||||
responsibilities: [...prev.responsibilities, responsibilityInput.trim()],
|
||||
}))
|
||||
setResponsibilityInput('')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const removeResponsibility = (index: number) => {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
responsibilities: prev.responsibilities.filter((_, i) => i !== index),
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const addQualification = () => {
|
||||
if (
|
||||
qualificationInput.trim() &&
|
||||
!formData.qualifications.includes(qualificationInput.trim())
|
||||
) {
|
||||
if (qualificationInput.trim() && !formData.qualifications.includes(qualificationInput.trim())) {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
qualifications: [...prev.qualifications, qualificationInput.trim()],
|
||||
}));
|
||||
setQualificationInput("");
|
||||
}))
|
||||
setQualificationInput('')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const removeQualification = (index: number) => {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
qualifications: prev.qualifications.filter((_, i) => i !== index),
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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="flex items-center justify-between p-3 border-b">
|
||||
<h2 className="text-xl font-bold text-gray-900">{title}</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="p-1 hover:bg-gray-100 rounded-full"
|
||||
>
|
||||
<button onClick={onClose} className="p-1 hover:bg-gray-100 rounded-full">
|
||||
<FaTimes className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -214,47 +201,37 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
autoFocus
|
||||
type="text"
|
||||
value={formData.positionCode}
|
||||
onChange={(e) =>
|
||||
handleInputChange("positionCode", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.positionCode ? "border-red-500" : "border-gray-300"
|
||||
errors.positionCode ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Örn: DEV-001"
|
||||
/>
|
||||
{errors.positionCode && (
|
||||
<p className="text-red-500 text-sm mt-1">
|
||||
{errors.positionCode}
|
||||
</p>
|
||||
<p className="text-red-500 text-sm mt-1">{errors.positionCode}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Pozisyon Adı *
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Pozisyon Adı *</label>
|
||||
<input
|
||||
type="text"
|
||||
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 ${
|
||||
errors.title ? "border-red-500" : "border-gray-300"
|
||||
errors.title ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="Örn: Software Developer"
|
||||
/>
|
||||
{errors.title && (
|
||||
<p className="text-red-500 text-sm mt-1">{errors.title}</p>
|
||||
)}
|
||||
{errors.title && <p className="text-red-500 text-sm mt-1">{errors.title}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Açıklama
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Açıklama</label>
|
||||
<textarea
|
||||
value={formData.description}
|
||||
onChange={(e) => handleInputChange("description", e.target.value)}
|
||||
onChange={(e) => handleInputChange('description', e.target.value)}
|
||||
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"
|
||||
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>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Departman *
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Departman *</label>
|
||||
<select
|
||||
value={formData.departmentId}
|
||||
onChange={(e) =>
|
||||
handleInputChange("departmentId", e.target.value)
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.departmentId ? "border-red-500" : "border-gray-300"
|
||||
errors.departmentId ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
>
|
||||
<option value="">Departman seçin</option>
|
||||
|
|
@ -283,33 +256,22 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
))}
|
||||
</select>
|
||||
{errors.departmentId && (
|
||||
<p className="text-red-500 text-sm mt-1">
|
||||
{errors.departmentId}
|
||||
</p>
|
||||
<p className="text-red-500 text-sm mt-1">{errors.departmentId}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Seviye
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Seviye</label>
|
||||
<select
|
||||
value={formData.level}
|
||||
onChange={(e) =>
|
||||
handleInputChange("level", e.target.value as JobLevelEnum)
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value={JobLevelEnum.Entry}>Giriş Seviyesi</option>
|
||||
<option value={JobLevelEnum.Junior}>Junior</option>
|
||||
<option value={JobLevelEnum.Mid}>Orta Seviye</option>
|
||||
<option value={JobLevelEnum.Senior}>Senior</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>
|
||||
{Object.values(JobLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getJobLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -317,23 +279,17 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
{/* Salary Information */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Minimum Maaş *
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Minimum Maaş *</label>
|
||||
<input
|
||||
type="number"
|
||||
value={formData.minSalary}
|
||||
onChange={(e) =>
|
||||
handleInputChange("minSalary", Number(e.target.value))
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.minSalary ? "border-red-500" : "border-gray-300"
|
||||
errors.minSalary ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
min="0"
|
||||
/>
|
||||
{errors.minSalary && (
|
||||
<p className="text-red-500 text-sm mt-1">{errors.minSalary}</p>
|
||||
)}
|
||||
{errors.minSalary && <p className="text-red-500 text-sm mt-1">{errors.minSalary}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -343,31 +299,27 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
<input
|
||||
type="number"
|
||||
value={formData.maxSalary}
|
||||
onChange={(e) =>
|
||||
handleInputChange("maxSalary", Number(e.target.value))
|
||||
}
|
||||
onChange={(e) => 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 ${
|
||||
errors.maxSalary ? "border-red-500" : "border-gray-300"
|
||||
errors.maxSalary ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
min="0"
|
||||
/>
|
||||
{errors.maxSalary && (
|
||||
<p className="text-red-500 text-sm mt-1">{errors.maxSalary}</p>
|
||||
)}
|
||||
{errors.maxSalary && <p className="text-red-500 text-sm mt-1">{errors.maxSalary}</p>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Para Birimi
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||
<select
|
||||
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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -382,9 +334,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
type="text"
|
||||
value={skillInput}
|
||||
onChange={(e) => setSkillInput(e.target.value)}
|
||||
onKeyPress={(e) =>
|
||||
e.key === "Enter" && (e.preventDefault(), addSkill())
|
||||
}
|
||||
onKeyPress={(e) => 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"
|
||||
placeholder="Yetenek ekleyin..."
|
||||
/>
|
||||
|
|
@ -417,17 +367,13 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
|
||||
{/* Responsibilities */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Sorumluluklar
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Sorumluluklar</label>
|
||||
<div className="flex gap-2 mb-2">
|
||||
<input
|
||||
type="text"
|
||||
value={responsibilityInput}
|
||||
onChange={(e) => setResponsibilityInput(e.target.value)}
|
||||
onKeyPress={(e) =>
|
||||
e.key === "Enter" && (e.preventDefault(), addResponsibility())
|
||||
}
|
||||
onKeyPress={(e) => 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"
|
||||
placeholder="Sorumluluk ekleyin..."
|
||||
/>
|
||||
|
|
@ -445,9 +391,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
key={index}
|
||||
className="flex items-center justify-between p-2 bg-green-50 rounded-md text-sm"
|
||||
>
|
||||
<span className="text-green-800 text-sm">
|
||||
{responsibility}
|
||||
</span>
|
||||
<span className="text-green-800 text-sm">{responsibility}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => removeResponsibility(index)}
|
||||
|
|
@ -462,17 +406,13 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
|
||||
{/* Qualifications */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
Nitelikler
|
||||
</label>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Nitelikler</label>
|
||||
<div className="flex gap-2 mb-2">
|
||||
<input
|
||||
type="text"
|
||||
value={qualificationInput}
|
||||
onChange={(e) => setQualificationInput(e.target.value)}
|
||||
onKeyPress={(e) =>
|
||||
e.key === "Enter" && (e.preventDefault(), addQualification())
|
||||
}
|
||||
onKeyPress={(e) => 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"
|
||||
placeholder="Nitelik ekleyin..."
|
||||
/>
|
||||
|
|
@ -490,9 +430,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
key={index}
|
||||
className="flex items-center justify-between p-2 bg-purple-50 rounded-md text-sm"
|
||||
>
|
||||
<span className="text-purple-800 text-sm">
|
||||
{qualification}
|
||||
</span>
|
||||
<span className="text-purple-800 text-sm">{qualification}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => removeQualification(index)}
|
||||
|
|
@ -511,13 +449,10 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
type="checkbox"
|
||||
id="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"
|
||||
/>
|
||||
<label
|
||||
htmlFor="isActive"
|
||||
className="ml-2 block text-sm text-gray-900"
|
||||
>
|
||||
<label htmlFor="isActive" className="ml-2 block text-sm text-gray-900">
|
||||
Aktif pozisyon
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -543,7 +478,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default JobPositionFormModal;
|
||||
export default JobPositionFormModal
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
<h2 className="text-2xl font-bold text-gray-900">İş Pozisyonları</h2>
|
||||
<p className="text-gray-600">
|
||||
Şirket pozisyonları ve iş tanımları yönetimi
|
||||
</p>
|
||||
<p className="text-gray-600">Şirket pozisyonları ve iş tanımları yönetimi</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
{/* 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]"
|
||||
>
|
||||
<option value="all">Tüm Seviyeler</option>
|
||||
<option value={JobLevelEnum.Entry}>Giriş Seviyesi</option>
|
||||
<option value={JobLevelEnum.Junior}>Junior</option>
|
||||
<option value={JobLevelEnum.Mid}>Orta Seviye</option>
|
||||
<option value={JobLevelEnum.Senior}>Senior</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>
|
||||
{Object.values(JobLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getJobLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={LeaveStatusEnum.Pending}>Beklemede</option>
|
||||
<option value={LeaveStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={LeaveStatusEnum.Rejected}>Reddedildi</option>
|
||||
<option value={LeaveStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(LeaveStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getLeaveStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tüm İzin Türleri</option>
|
||||
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option>
|
||||
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option>
|
||||
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option>
|
||||
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</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>
|
||||
{Object.values(LeaveTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getLeaveTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</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"
|
||||
>
|
||||
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option>
|
||||
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option>
|
||||
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option>
|
||||
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</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>
|
||||
{Object.values(LeaveTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getLeaveTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option>
|
||||
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option>
|
||||
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option>
|
||||
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</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>
|
||||
{Object.values(LeaveStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getLeaveStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={LeaveStatusEnum.Pending}>Beklemede</option>
|
||||
<option value={LeaveStatusEnum.Approved}>Onaylı</option>
|
||||
<option value={LeaveStatusEnum.Rejected}>Reddedildi</option>
|
||||
{Object.values(LeaveStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getLeaveStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={PayrollStatusEnum.Draft}>Taslak</option>
|
||||
<option value={PayrollStatusEnum.Calculated}>Hesaplandı</option>
|
||||
<option value={PayrollStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={PayrollStatusEnum.Paid}>Ödendi</option>
|
||||
<option value={PayrollStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(PayrollStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getPayrollStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
|
|
|
|||
|
|
@ -137,12 +137,21 @@ const ChangeNotificationStatusModal: React.FC<ChangeNotificationStatusModalProps
|
|||
errors.status ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
>
|
||||
<option value={NotificationStatusEnum.Open}>Açık</option>
|
||||
<option value={NotificationStatusEnum.Assigned}>Atandı</option>
|
||||
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option>
|
||||
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
|
||||
<option value={NotificationStatusEnum.Rejected}>Reddedildi</option>
|
||||
{Object.keys(NotificationStatusEnum).map((key) => (
|
||||
<option
|
||||
key={key}
|
||||
value={NotificationStatusEnum[key as keyof typeof NotificationStatusEnum]}
|
||||
>
|
||||
{getNotificationStatusText(
|
||||
NotificationStatusEnum[key as keyof typeof NotificationStatusEnum],
|
||||
)}
|
||||
</option>
|
||||
))}
|
||||
{Object.values(NotificationStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getNotificationStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.status && <p className="text-red-500 text-sm mt-1">{errors.status}</p>}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
|
|||
import { PmFaultNotification, WorkOrderTypeEnum } from '../../../types/pm'
|
||||
import { MrpWorkOrder } from '../../../types/mrp'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityText, getWorkOrderTypeText } from '@/utils/erp'
|
||||
|
||||
interface CreateWorkOrderFromNotificationModalProps {
|
||||
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"
|
||||
>
|
||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici Bakım</option>
|
||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici Bakım</option>
|
||||
<option value={WorkOrderTypeEnum.Emergency}>Acil Müdahale</option>
|
||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
||||
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getWorkOrderTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -180,10 +181,11 @@ const CreateWorkOrderFromNotificationModal: React.FC<CreateWorkOrderFromNotifica
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from '../../../types/pm'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityColor } from '../../../utils/erp'
|
||||
import { getPriorityColor, getPriorityText } from '../../../utils/erp'
|
||||
|
||||
interface CreateWorkOrderModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -243,10 +243,11 @@ const CreateWorkOrderModal: React.FC<CreateWorkOrderModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Ortak ayarı kullan</option>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ import {
|
|||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import {
|
||||
getCriticalityLevelText,
|
||||
getFaultTypeText,
|
||||
getNotificationStatusText,
|
||||
getPriorityText,
|
||||
} from '@/utils/erp'
|
||||
|
||||
interface EditFaultNotificationModalProps {
|
||||
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"
|
||||
>
|
||||
<option value={NotificationStatusEnum.Open}>Açık</option>
|
||||
<option value={NotificationStatusEnum.Assigned}>Atandı</option>
|
||||
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option>
|
||||
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
|
||||
<option value={NotificationStatusEnum.Rejected}>Reddedildi</option>
|
||||
{Object.values(NotificationStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getNotificationStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -294,14 +299,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={FaultTypeEnum.Mechanical}>Mekanik</option>
|
||||
<option value={FaultTypeEnum.Electrical}>Elektrik</option>
|
||||
<option value={FaultTypeEnum.Hydraulic}>Hidrolik</option>
|
||||
<option value={FaultTypeEnum.Pneumatic}>Pnömatik</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>
|
||||
{Object.values(FaultTypeEnum).map((faultType) => (
|
||||
<option key={faultType} value={faultType}>
|
||||
{getFaultTypeText(faultType)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -312,10 +314,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
|||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { mockUnits } from '../../../mocks/mockUnits'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getFrequencyUnitText, getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
|
||||
|
||||
interface EditMaintenancePlanModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -154,10 +155,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option>
|
||||
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getMaintenancePlanTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -168,10 +170,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="md:col-span-2">
|
||||
|
|
@ -214,12 +217,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={FrequencyUnitEnum.Days}>Gün</option>
|
||||
<option value={FrequencyUnitEnum.Weeks}>Hafta</option>
|
||||
<option value={FrequencyUnitEnum.Months}>Ay</option>
|
||||
<option value={FrequencyUnitEnum.Years}>Yıl</option>
|
||||
<option value={FrequencyUnitEnum.Hours}>Saat</option>
|
||||
<option value={FrequencyUnitEnum.Cycles}>Çevrim</option>
|
||||
{Object.values(FrequencyUnitEnum).map((unit) => (
|
||||
<option key={unit} value={unit}>
|
||||
{getFrequencyUnitText(unit)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { FaTimes, FaSave, FaPlus, FaMinus } from 'react-icons/fa'
|
|||
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
||||
import { getTeamRoleText } from '@/utils/erp'
|
||||
|
||||
interface EditTeamModalProps {
|
||||
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"
|
||||
>
|
||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
||||
<option value={TeamRoleEnum.Lead}>Lider</option>
|
||||
<option value={TeamRoleEnum.Specialist}>Uzman</option>
|
||||
{Object.values(TeamRoleEnum)
|
||||
.filter((a) => a !== TeamRoleEnum.Manager)
|
||||
.map((role) => (
|
||||
<option key={role} value={role}>
|
||||
{getTeamRoleText(role)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import {
|
|||
PmWorkCenterSpecification,
|
||||
} from '../../../types/pm'
|
||||
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
|
||||
import { mockWorkCenterMachineTypes } from '@/mocks/mockWorkCenterMachineTypes'
|
||||
|
||||
interface EditWorkCenterModalProps {
|
||||
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>
|
||||
<select
|
||||
name="machineType"
|
||||
value={formData.machineType || 'Manual'}
|
||||
value={formData.machineType?.id}
|
||||
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"
|
||||
>
|
||||
<option value="Manual">Manuel</option>
|
||||
<option value="CNC">CNC</option>
|
||||
<option value="Automated">Otomatik</option>
|
||||
<option value="Semi-Automated">Yarı Otomatik</option>
|
||||
{mockWorkCenterMachineTypes.map((type) => (
|
||||
<option key={type.id} value={type.id}>
|
||||
{type.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -290,10 +293,11 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
||||
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkCenterStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -306,10 +310,11 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
|
|||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityText, getWorkOrderStatusText, getWorkOrderTypeText } from '@/utils/erp'
|
||||
|
||||
interface EditWorkOrderModalProps {
|
||||
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"
|
||||
>
|
||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option>
|
||||
<option value={WorkOrderStatusEnum.Released}>Serbest Bırakıldı</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>
|
||||
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option>
|
||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option>
|
||||
<option value={WorkOrderTypeEnum.Emergency}>Acil</option>
|
||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
||||
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getWorkOrderTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -254,12 +254,11 @@ const FaultNotifications: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={NotificationStatusEnum.Open}>Açık</option>
|
||||
<option value={NotificationStatusEnum.Assigned}>Atandı</option>
|
||||
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option>
|
||||
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
|
||||
{Object.values(NotificationStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getNotificationStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<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"
|
||||
>
|
||||
<option value="all">Tüm Öncelikler</option>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
getPriorityColor,
|
||||
getWorkOrderStatusColor,
|
||||
getWorkOrderStatusIcon,
|
||||
getWorkOrderStatusText,
|
||||
} from '../../../utils/erp'
|
||||
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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value="scheduled">Planlanmış</option>
|
||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
|
||||
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
PmMaintenancePlan,
|
||||
} from '../../../types/pm'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
|
||||
|
||||
interface MaintenancePlanModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -123,10 +124,11 @@ const MaintenancePlanModal: React.FC<MaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option>
|
||||
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getMaintenancePlanTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -137,10 +139,11 @@ const MaintenancePlanModal: React.FC<MaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import PlanStatusChangeModal from './PlanStatusChangeModal'
|
|||
import Widget from '../../../components/common/Widget'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import {
|
||||
getFrequencyUnitText,
|
||||
getFrequencyUnitTextByFrequency,
|
||||
getMaintenancePlanTypeColor,
|
||||
getMaintenancePlanTypeText,
|
||||
getPriorityColor,
|
||||
|
|
@ -194,11 +194,11 @@ const MaintenancePlans: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="all">Tüm Tipler</option>
|
||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici</option>
|
||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici</option>
|
||||
<option value={MaintenancePlanTypeEnum.Predictive}>Tahminsel</option>
|
||||
<option value={MaintenancePlanTypeEnum.Condition}>Duruma Bağlı</option>
|
||||
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getMaintenancePlanTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="relative">
|
||||
|
|
@ -313,7 +313,7 @@ const MaintenancePlans: React.FC = () => {
|
|||
</td>
|
||||
<td className="px-4 py-3 whitespace-nowrap">
|
||||
<div className="text-sm text-gray-900">
|
||||
{getFrequencyUnitText(plan.frequency, plan.frequencyUnit)}
|
||||
{getFrequencyUnitTextByFrequency(plan.frequency, plan.frequencyUnit)}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">{plan.estimatedDuration} dakika</div>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Roller</option>
|
||||
<option value={TeamRoleEnum.Lead}>Lider</option>
|
||||
<option value={TeamRoleEnum.Specialist}>Uzman</option>
|
||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
||||
{Object.values(TeamRoleEnum).map((role) => (
|
||||
<option key={role} value={role}>
|
||||
{getTeamRoleText(role)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="relative">
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option>
|
||||
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
|
||||
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<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"
|
||||
>
|
||||
<option value="all">Tüm Tipler</option>
|
||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option>
|
||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option>
|
||||
<option value={WorkOrderTypeEnum.Emergency}>Acil</option>
|
||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
||||
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getWorkOrderTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { PmCalendarEvent, WorkOrderStatusEnum } from '../../../types/pm'
|
|||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityText, getWorkOrderStatusText } from '@/utils/erp'
|
||||
|
||||
interface NewCalendarEventModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -220,10 +221,11 @@ const NewCalendarEventModal: React.FC<NewCalendarEventModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="scheduled">Planlanmış</option>
|
||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option>
|
||||
<option value={WorkOrderStatusEnum.Released}>Serbest Bırakıldı</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>
|
||||
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getCriticalityLevelText, getFaultTypeText, getPriorityText } from '@/utils/erp'
|
||||
|
||||
interface NewFaultNotificationModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -274,14 +275,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={FaultTypeEnum.Mechanical}>Mekanik</option>
|
||||
<option value={FaultTypeEnum.Electrical}>Elektrik</option>
|
||||
<option value={FaultTypeEnum.Hydraulic}>Hidrolik</option>
|
||||
<option value={FaultTypeEnum.Pneumatic}>Pnömatik</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>
|
||||
{Object.values(FaultTypeEnum).map((faultType) => (
|
||||
<option key={faultType} value={faultType}>
|
||||
{getFaultTypeText(faultType)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -292,10 +290,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
|||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { mockUnits } from '../../../mocks/mockUnits'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getFrequencyUnitText, getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
|
||||
|
||||
interface NewMaintenancePlanModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -158,10 +159,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option>
|
||||
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option>
|
||||
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getMaintenancePlanTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -172,10 +174,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="md:col-span-2">
|
||||
|
|
@ -219,12 +222,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={FrequencyUnitEnum.Days}>Gün</option>
|
||||
<option value={FrequencyUnitEnum.Weeks}>Hafta</option>
|
||||
<option value={FrequencyUnitEnum.Months}>Ay</option>
|
||||
<option value={FrequencyUnitEnum.Years}>Yıl</option>
|
||||
<option value={FrequencyUnitEnum.Hours}>Saat</option>
|
||||
<option value={FrequencyUnitEnum.Cycles}>Çevrim</option>
|
||||
{Object.values(FrequencyUnitEnum).map((unit) => (
|
||||
<option key={unit} value={unit}>
|
||||
{getFrequencyUnitText(unit)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { TeamRoleEnum } from '../../../types/common'
|
|||
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { Team, TeamMember } from '../../../types/common'
|
||||
import { getTeamRoleText } from '@/utils/erp'
|
||||
|
||||
interface NewTeamModalProps {
|
||||
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"
|
||||
>
|
||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
||||
<option value={TeamRoleEnum.Lead}>Lider</option>
|
||||
<option value={TeamRoleEnum.Specialist}>Uzman</option>
|
||||
<option value={TeamRoleEnum.Manager}>Yönetici</option>
|
||||
{Object.values(TeamRoleEnum).map((role) => (
|
||||
<option key={role} value={role}>
|
||||
{getTeamRoleText(role)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
CriticalityLevelEnum,
|
||||
PmWorkCenterSpecification,
|
||||
} from '../../../types/pm'
|
||||
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
|
||||
|
||||
interface NewWorkCenterModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -249,10 +250,11 @@ const NewWorkCenterModal: React.FC<NewWorkCenterModalProps> = ({ isOpen, onClose
|
|||
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"
|
||||
>
|
||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
||||
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkCenterStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -265,10 +267,11 @@ const NewWorkCenterModal: React.FC<NewWorkCenterModalProps> = ({ isOpen, onClose
|
|||
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"
|
||||
>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
|
|||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityText, getWorkOrderTypeText } from '@/utils/erp'
|
||||
|
||||
interface NewWorkOrderModalProps {
|
||||
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"
|
||||
>
|
||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option>
|
||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option>
|
||||
<option value={WorkOrderTypeEnum.Emergency}>Acil</option>
|
||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
||||
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getWorkOrderTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -102,10 +102,11 @@ const StatusUpdateModal: React.FC<StatusUpdateModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
||||
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkCenterStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
{isStatusCritical && (
|
||||
|
|
@ -145,10 +146,11 @@ const StatusUpdateModal: React.FC<StatusUpdateModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
||||
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkCenterStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="relative">
|
||||
|
|
@ -250,11 +251,11 @@ const WorkCenterCards: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="all">Tüm Kritiklik</option>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { mockDepartments } from '../../../mocks/mockDepartments'
|
|||
import { HrDepartment } from '../../../types/hr'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
|
||||
|
||||
interface ValidationErrors {
|
||||
[key: string]: string
|
||||
|
|
@ -65,7 +66,7 @@ const WorkCenterForm: React.FC = () => {
|
|||
capacity: 0,
|
||||
costPerHour: 0,
|
||||
setupTime: 0,
|
||||
machineType: '',
|
||||
machineTypeId: '',
|
||||
isActive: true,
|
||||
creationTime: new Date('2022-03-15'),
|
||||
lastModificationTime: new Date('2024-01-15'),
|
||||
|
|
@ -288,12 +289,11 @@ const WorkCenterForm: React.FC = () => {
|
|||
}`}
|
||||
>
|
||||
<option value="">Tip seçin</option>
|
||||
<option value="MACHINE">Makine</option>
|
||||
<option value="VEHICLE">Araç</option>
|
||||
<option value="TOOL">Alet</option>
|
||||
<option value="FACILITY">Tesis</option>
|
||||
<option value="SYSTEM">Sistem</option>
|
||||
<option value="OTHER">Diğer</option>
|
||||
{mockWorkCenters.map((wc) => (
|
||||
<option key={wc.workCenterType?.id} value={wc.workCenterType?.id}>
|
||||
{wc.workCenterType?.code} - {wc.workCenterType?.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.workCenterType && (
|
||||
<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)}
|
||||
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>
|
||||
<option value="DOWN">Arızalı</option>
|
||||
<option value="MAINTENANCE">Bakımda</option>
|
||||
<option value="RETIRED">Kullanım Dışı</option>
|
||||
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkCenterStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -444,10 +445,11 @@ const WorkCenterForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="LOW">Düşük</option>
|
||||
<option value="MEDIUM">Orta</option>
|
||||
<option value="HIGH">Yüksek</option>
|
||||
<option value="CRITICAL">Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
||||
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkCenterStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
||||
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||
<option key={level} value={level}>
|
||||
{getCriticalityLevelText(level)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
} from 'react-icons/fa'
|
||||
import { MrpBOM, MrpBOMComponent, MrpBOMOperation } from '../../../types/mrp'
|
||||
import BOMFormModal from './BOMFormModal'
|
||||
import { getBOMTypeColor, getBOMTypeName } from '../../../utils/erp'
|
||||
import { getBOMTypeColor, getBOMTypeText } from '../../../utils/erp'
|
||||
import { mockBOMs } from '../../../mocks/mockBOMs'
|
||||
import { Container } from '@/components/shared'
|
||||
|
||||
|
|
@ -82,9 +82,7 @@ const BOMManagement: React.FC = () => {
|
|||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-gray-900">Ürün Ağaçları (BOM)</h2>
|
||||
<p className="text-gray-600">
|
||||
Ürün bileşenlerini ve üretim operasyonlarını yönetin
|
||||
</p>
|
||||
<p className="text-gray-600">Ürün bileşenlerini ve üretim operasyonlarını yönetin</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleAddNew}
|
||||
|
|
@ -126,7 +124,7 @@ const BOMManagement: React.FC = () => {
|
|||
bom.bomType,
|
||||
)}`}
|
||||
>
|
||||
{getBOMTypeName(bom.bomType)}
|
||||
{getBOMTypeText(bom.bomType)}
|
||||
</span>
|
||||
</div>
|
||||
<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}
|
||||
</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>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaTimes, FaSave } from "react-icons/fa";
|
||||
import { MrpDemandForecast, ForecastMethodEnum } from "../../../types/mrp";
|
||||
import { mockMaterials } from "../../../mocks/mockMaterials";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaTimes, FaSave } from 'react-icons/fa'
|
||||
import { MrpDemandForecast, ForecastMethodEnum } from '../../../types/mrp'
|
||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { getForecastMethodText } from '@/utils/erp'
|
||||
|
||||
interface DemandForecastFormModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (
|
||||
forecastData: Omit<MrpDemandForecast, "id" | "material"> & { id?: string }
|
||||
) => void;
|
||||
initialData: MrpDemandForecast | null;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (forecastData: Omit<MrpDemandForecast, 'id' | 'material'> & { id?: string }) => void
|
||||
initialData: MrpDemandForecast | null
|
||||
}
|
||||
|
||||
const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||
|
|
@ -19,9 +18,9 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
initialData,
|
||||
}) => {
|
||||
const newFormData: MrpDemandForecast = {
|
||||
id: "",
|
||||
materialId: "",
|
||||
forecastPeriod: "",
|
||||
id: '',
|
||||
materialId: '',
|
||||
forecastPeriod: '',
|
||||
startDate: new Date(),
|
||||
endDate: new Date(),
|
||||
forecastMethod: ForecastMethodEnum.MovingAverage,
|
||||
|
|
@ -32,10 +31,10 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
trendFactor: 0,
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
notes: "",
|
||||
};
|
||||
notes: '',
|
||||
}
|
||||
|
||||
const [formData, setFormData] = useState(newFormData);
|
||||
const [formData, setFormData] = useState(newFormData)
|
||||
|
||||
useEffect(() => {
|
||||
if (initialData) {
|
||||
|
|
@ -43,36 +42,33 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
...initialData,
|
||||
startDate: new Date(initialData.startDate),
|
||||
endDate: new Date(initialData.endDate),
|
||||
});
|
||||
})
|
||||
} else {
|
||||
setFormData(newFormData);
|
||||
setFormData(newFormData)
|
||||
}
|
||||
}, [initialData, isOpen]);
|
||||
}, [initialData, isOpen])
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
const saveData = {
|
||||
...formData,
|
||||
id: initialData?.id,
|
||||
startDate: new Date(formData.startDate),
|
||||
endDate: new Date(formData.endDate),
|
||||
};
|
||||
onSave(saveData);
|
||||
};
|
||||
}
|
||||
onSave(saveData)
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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="flex items-center justify-between p-4 border-b">
|
||||
<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>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<FaTimes className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -80,15 +76,11 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
<form onSubmit={handleSubmit} className="p-4 space-y-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Malzeme
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Malzeme</label>
|
||||
<select
|
||||
required
|
||||
value={formData.materialId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, materialId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Seçiniz</option>
|
||||
|
|
@ -108,9 +100,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
type="text"
|
||||
required
|
||||
value={formData.forecastPeriod}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, forecastPeriod: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
placeholder="Örn: 2024-Q3"
|
||||
/>
|
||||
|
|
@ -123,7 +113,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
<input
|
||||
type="date"
|
||||
required
|
||||
value={formData.startDate.toISOString().split("T")[0]}
|
||||
value={formData.startDate.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -135,13 +125,11 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Bitiş Tarihi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Bitiş Tarihi</label>
|
||||
<input
|
||||
type="date"
|
||||
required
|
||||
value={formData.endDate.toISOString().split("T")[0]}
|
||||
value={formData.endDate.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -153,9 +141,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Tahmin Yöntemi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Tahmin Yöntemi</label>
|
||||
<select
|
||||
required
|
||||
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"
|
||||
>
|
||||
<option value={ForecastMethodEnum.MovingAverage}>
|
||||
Hareketli Ortalama
|
||||
</option>
|
||||
<option value={ForecastMethodEnum.ExponentialSmoothing}>
|
||||
Üstel Yumuşatma
|
||||
</option>
|
||||
<option value={ForecastMethodEnum.LinearRegression}>
|
||||
Doğrusal Regresyon
|
||||
</option>
|
||||
<option value={ForecastMethodEnum.Seasonal}>Mevsimsel</option>
|
||||
{Object.values(ForecastMethodEnum).map((method) => (
|
||||
<option key={method} value={method}>
|
||||
{getForecastMethodText(method)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Tahmin Miktarı
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Tahmin Miktarı</label>
|
||||
<input
|
||||
type="number"
|
||||
required
|
||||
|
|
@ -219,7 +198,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default DemandForecastFormModal;
|
||||
export default DemandForecastFormModal
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaTimes, FaSave } from "react-icons/fa";
|
||||
import { MrpWorkOrder } from "../../../types/mrp";
|
||||
import { mockProductionOrders } from "../../../mocks/mockProductionOrders";
|
||||
import { mockOperations } from "../../../mocks/mockOperations";
|
||||
import { mockMaterials } from "../../../mocks/mockMaterials";
|
||||
import { mockWorkCenters } from "../../../mocks/mockWorkCenters";
|
||||
import { WorkOrderStatusEnum } from "../../../types/pm";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaTimes, FaSave } from 'react-icons/fa'
|
||||
import { MrpWorkOrder } from '../../../types/mrp'
|
||||
import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
|
||||
import { mockOperations } from '../../../mocks/mockOperations'
|
||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||
import { WorkOrderStatusEnum } from '../../../types/pm'
|
||||
import { getWorkOrderStatusText } from '@/utils/erp'
|
||||
|
||||
interface EditWorkOrderFormProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (workOrder: MrpWorkOrder) => void;
|
||||
workOrder: MrpWorkOrder | null;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (workOrder: MrpWorkOrder) => void
|
||||
workOrder: MrpWorkOrder | null
|
||||
}
|
||||
|
||||
const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||
|
|
@ -21,20 +22,20 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
workOrder,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState({
|
||||
workOrderNumber: "",
|
||||
productionOrderId: "",
|
||||
operationId: "",
|
||||
materialId: "",
|
||||
workOrderNumber: '',
|
||||
productionOrderId: '',
|
||||
operationId: '',
|
||||
materialId: '',
|
||||
sequence: 1,
|
||||
plannedStartDate: "",
|
||||
plannedEndDate: "",
|
||||
plannedStartDate: '',
|
||||
plannedEndDate: '',
|
||||
plannedQuantity: 0,
|
||||
workCenterId: "",
|
||||
workCenterId: '',
|
||||
assignedOperators: [] as string[],
|
||||
setupTime: 0,
|
||||
processTime: 0,
|
||||
status: WorkOrderStatusEnum.Created,
|
||||
});
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (workOrder) {
|
||||
|
|
@ -44,23 +45,21 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
operationId: workOrder.operationId,
|
||||
materialId: workOrder.materialId,
|
||||
sequence: workOrder.sequence,
|
||||
plannedStartDate: workOrder.plannedStartDate
|
||||
.toISOString()
|
||||
.split("T")[0],
|
||||
plannedEndDate: workOrder.plannedEndDate.toISOString().split("T")[0],
|
||||
plannedStartDate: workOrder.plannedStartDate.toISOString().split('T')[0],
|
||||
plannedEndDate: workOrder.plannedEndDate.toISOString().split('T')[0],
|
||||
plannedQuantity: workOrder.plannedQuantity,
|
||||
workCenterId: workOrder.workCenterId,
|
||||
assignedOperators: workOrder.assignedOperators,
|
||||
setupTime: workOrder.setupTime,
|
||||
processTime: workOrder.processTime,
|
||||
status: workOrder.status,
|
||||
});
|
||||
})
|
||||
}
|
||||
}, [workOrder]);
|
||||
}, [workOrder])
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!workOrder) return;
|
||||
e.preventDefault()
|
||||
if (!workOrder) return
|
||||
|
||||
const updatedWorkOrder: MrpWorkOrder = {
|
||||
...workOrder,
|
||||
|
|
@ -68,24 +67,19 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
plannedStartDate: new Date(formData.plannedStartDate),
|
||||
plannedEndDate: new Date(formData.plannedEndDate),
|
||||
lastModificationTime: new Date(),
|
||||
};
|
||||
onSave(updatedWorkOrder);
|
||||
onClose();
|
||||
};
|
||||
}
|
||||
onSave(updatedWorkOrder)
|
||||
onClose()
|
||||
}
|
||||
|
||||
if (!isOpen || !workOrder) return null;
|
||||
if (!isOpen || !workOrder) return null
|
||||
|
||||
return (
|
||||
<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="flex items-center justify-between p-4 border-b">
|
||||
<h2 className="text-lg font-semibold text-gray-900">
|
||||
İş Emri Düzenle
|
||||
</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<h2 className="text-lg font-semibold text-gray-900">İş Emri Düzenle</h2>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<FaTimes className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -100,18 +94,14 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
type="text"
|
||||
required
|
||||
value={formData.workOrderNumber}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, workOrderNumber: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
placeholder="WO-2024-XXX"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Üretim Emri
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Üretim Emri</label>
|
||||
<select
|
||||
required
|
||||
value={formData.productionOrderId}
|
||||
|
|
@ -133,15 +123,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Operasyon
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Operasyon</label>
|
||||
<select
|
||||
required
|
||||
value={formData.operationId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, operationId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Seçiniz</option>
|
||||
|
|
@ -154,15 +140,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Malzeme
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Malzeme</label>
|
||||
<select
|
||||
required
|
||||
value={formData.materialId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, materialId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Seçiniz</option>
|
||||
|
|
@ -175,15 +157,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
İş Merkezi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">İş Merkezi</label>
|
||||
<select
|
||||
required
|
||||
value={formData.workCenterId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, workCenterId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Seçiniz</option>
|
||||
|
|
@ -196,9 +174,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Sıra
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Sıra</label>
|
||||
<input
|
||||
type="number"
|
||||
required
|
||||
|
|
@ -222,9 +198,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
type="date"
|
||||
required
|
||||
value={formData.plannedStartDate}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, plannedStartDate: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -237,9 +211,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
type="date"
|
||||
required
|
||||
value={formData.plannedEndDate}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, plannedEndDate: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -302,9 +274,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Durum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||
<select
|
||||
value={formData.status}
|
||||
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"
|
||||
>
|
||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={WorkOrderStatusEnum.Released}>Yayınlandı</option>
|
||||
<option value={WorkOrderStatusEnum.InProgress}>İşlemde</option>
|
||||
<option value={WorkOrderStatusEnum.Completed}>
|
||||
Tamamlandı
|
||||
</option>
|
||||
<option value={WorkOrderStatusEnum.Cancelled}>
|
||||
İptal Edildi
|
||||
</option>
|
||||
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getWorkOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -347,7 +313,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default EditWorkOrderForm;
|
||||
export default EditWorkOrderForm
|
||||
|
|
|
|||
|
|
@ -1,25 +1,24 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaTimes, FaSave } from "react-icons/fa";
|
||||
import {
|
||||
MrpMaterialRequirement,
|
||||
RequirementSourceTypeEnum,
|
||||
} from "../../../types/mrp";
|
||||
import { mockMaterials } from "../../../mocks/mockMaterials";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaTimes, FaSave } from 'react-icons/fa'
|
||||
import { MrpMaterialRequirement, RequirementSourceTypeEnum } from '../../../types/mrp'
|
||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||
import { getRequirementSourceTypeText } from '@/utils/erp'
|
||||
|
||||
interface MaterialRequirementFormModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (
|
||||
reqData: Omit<MrpMaterialRequirement, "id" | "material"> & { id?: string }
|
||||
) => void;
|
||||
initialData: MrpMaterialRequirement | null;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (reqData: Omit<MrpMaterialRequirement, 'id' | 'material'> & { id?: string }) => void
|
||||
initialData: MrpMaterialRequirement | null
|
||||
}
|
||||
|
||||
const MaterialRequirementFormModal: React.FC<
|
||||
MaterialRequirementFormModalProps
|
||||
> = ({ isOpen, onClose, onSave, initialData }) => {
|
||||
const MaterialRequirementFormModal: React.FC<MaterialRequirementFormModalProps> = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
onSave,
|
||||
initialData,
|
||||
}) => {
|
||||
const newFormData: MrpMaterialRequirement = {
|
||||
materialId: "",
|
||||
materialId: '',
|
||||
sourceType: RequirementSourceTypeEnum.Forecast,
|
||||
grossRequirement: 0,
|
||||
netRequirement: 0,
|
||||
|
|
@ -29,14 +28,14 @@ const MaterialRequirementFormModal: React.FC<
|
|||
plannedOrderRelease: 0,
|
||||
requirementDate: new Date(),
|
||||
plannedReceiptDate: new Date(),
|
||||
id: "",
|
||||
mrpRunId: "",
|
||||
id: '',
|
||||
mrpRunId: '',
|
||||
plannedReleaseDate: new Date(),
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
};
|
||||
}
|
||||
|
||||
const [formData, setFormData] = useState(newFormData);
|
||||
const [formData, setFormData] = useState(newFormData)
|
||||
|
||||
useEffect(() => {
|
||||
if (initialData) {
|
||||
|
|
@ -44,37 +43,34 @@ const MaterialRequirementFormModal: React.FC<
|
|||
...initialData,
|
||||
requirementDate: new Date(initialData.requirementDate),
|
||||
plannedReceiptDate: new Date(initialData.plannedReceiptDate),
|
||||
});
|
||||
})
|
||||
} else {
|
||||
// Reset form for new entry
|
||||
setFormData(newFormData);
|
||||
setFormData(newFormData)
|
||||
}
|
||||
}, [initialData, isOpen]);
|
||||
}, [initialData, isOpen])
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
const saveData = {
|
||||
...formData,
|
||||
id: initialData?.id,
|
||||
requirementDate: new Date(formData.requirementDate),
|
||||
plannedReceiptDate: new Date(formData.plannedReceiptDate),
|
||||
};
|
||||
onSave(saveData);
|
||||
};
|
||||
}
|
||||
onSave(saveData)
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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="flex items-center justify-between p-4 border-b">
|
||||
<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>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<FaTimes className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -82,15 +78,11 @@ const MaterialRequirementFormModal: React.FC<
|
|||
<form onSubmit={handleSubmit} className="p-4 space-y-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Malzeme
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Malzeme</label>
|
||||
<select
|
||||
required
|
||||
value={formData.materialId}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, materialId: e.target.value })
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Seçiniz</option>
|
||||
|
|
@ -103,9 +95,7 @@ const MaterialRequirementFormModal: React.FC<
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Kaynak Tipi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Kaynak Tipi</label>
|
||||
<select
|
||||
required
|
||||
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"
|
||||
>
|
||||
<option value={RequirementSourceTypeEnum.Forecast}>
|
||||
Tahmin
|
||||
</option>
|
||||
<option value={RequirementSourceTypeEnum.SalesOrder}>
|
||||
Satış Siparişi
|
||||
</option>
|
||||
<option value={RequirementSourceTypeEnum.SafetyStock}>
|
||||
Güvenlik Stoku
|
||||
</option>
|
||||
<option value={RequirementSourceTypeEnum.ProductionOrder}>
|
||||
Üretim Emri
|
||||
</option>
|
||||
{Object.values(RequirementSourceTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getRequirementSourceTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Brüt İhtiyaç
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Brüt İhtiyaç</label>
|
||||
<input
|
||||
type="number"
|
||||
required
|
||||
|
|
@ -152,9 +133,7 @@ const MaterialRequirementFormModal: React.FC<
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Net İhtiyaç
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Net İhtiyaç</label>
|
||||
<input
|
||||
type="number"
|
||||
required
|
||||
|
|
@ -170,13 +149,11 @@ const MaterialRequirementFormModal: React.FC<
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
İhtiyaç Tarihi
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">İhtiyaç Tarihi</label>
|
||||
<input
|
||||
type="date"
|
||||
required
|
||||
value={formData.requirementDate.toISOString().split("T")[0]}
|
||||
value={formData.requirementDate.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -194,7 +171,7 @@ const MaterialRequirementFormModal: React.FC<
|
|||
<input
|
||||
type="date"
|
||||
required
|
||||
value={formData.plannedReceiptDate.toISOString().split("T")[0]}
|
||||
value={formData.plannedReceiptDate.toISOString().split('T')[0]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
|
|
@ -225,7 +202,7 @@ const MaterialRequirementFormModal: React.FC<
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default MaterialRequirementFormModal;
|
||||
export default MaterialRequirementFormModal
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FaSave, FaTimes } from "react-icons/fa";
|
||||
import {
|
||||
OperationCategoryEnum,
|
||||
MrpOperationTypeDefinition,
|
||||
} from "../../../types/mrp";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaSave, FaTimes } from 'react-icons/fa'
|
||||
import { OperationCategoryEnum, MrpOperationTypeDefinition } from '../../../types/mrp'
|
||||
import { getOperationTypeText } from '@/utils/erp'
|
||||
|
||||
interface OperationTypeFormProps {
|
||||
open: boolean;
|
||||
initial?: MrpOperationTypeDefinition | null;
|
||||
onClose: () => void;
|
||||
onSave: (data: MrpOperationTypeDefinition) => void;
|
||||
open: boolean
|
||||
initial?: MrpOperationTypeDefinition | null
|
||||
onClose: () => void
|
||||
onSave: (data: MrpOperationTypeDefinition) => void
|
||||
}
|
||||
|
||||
const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||
|
|
@ -18,13 +16,13 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
|||
onClose,
|
||||
onSave,
|
||||
}) => {
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [form, setForm] = useState<MrpOperationTypeDefinition>(
|
||||
initial || {
|
||||
id: "",
|
||||
code: "",
|
||||
name: "",
|
||||
description: "",
|
||||
id: '',
|
||||
code: '',
|
||||
name: '',
|
||||
description: '',
|
||||
category: OperationCategoryEnum.Setup,
|
||||
defaultDuration: 0,
|
||||
requiresSetup: false,
|
||||
|
|
@ -34,85 +32,79 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
|||
isActive: true,
|
||||
creationTime: new Date(),
|
||||
lastModificationTime: new Date(),
|
||||
}
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (initial) setForm(initial);
|
||||
if (initial) setForm(initial)
|
||||
else
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
id: "",
|
||||
code: "",
|
||||
name: "",
|
||||
description: "",
|
||||
}));
|
||||
}, [initial, open]);
|
||||
id: '',
|
||||
code: '',
|
||||
name: '',
|
||||
description: '',
|
||||
}))
|
||||
}, [initial, open])
|
||||
|
||||
if (!open) return null;
|
||||
if (!open) return null
|
||||
|
||||
const handleChange = (
|
||||
field: keyof MrpOperationTypeDefinition,
|
||||
value: string | number | boolean
|
||||
value: string | number | boolean,
|
||||
) => {
|
||||
setForm((s) => ({
|
||||
...s,
|
||||
[field]: value,
|
||||
lastModificationTime: new Date(),
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
setSaving(true);
|
||||
setSaving(true)
|
||||
try {
|
||||
// simulate API
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
onSave({ ...form, id: form.id || String(Date.now()) });
|
||||
await new Promise((r) => setTimeout(r, 600))
|
||||
onSave({ ...form, id: form.id || String(Date.now()) })
|
||||
} finally {
|
||||
setSaving(false);
|
||||
setSaving(false)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<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">
|
||||
<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>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Kod
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Kod</label>
|
||||
<input
|
||||
autoFocus
|
||||
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"
|
||||
placeholder="Örn: CUT001"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Ad
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Ad</label>
|
||||
<input
|
||||
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"
|
||||
placeholder="Kesme İşlemi"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Açıklama
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama</label>
|
||||
<textarea
|
||||
value={form.description}
|
||||
onChange={(e) => handleChange("description", e.target.value)}
|
||||
onChange={(e) => handleChange('description', e.target.value)}
|
||||
rows={3}
|
||||
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>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Kategori
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Kategori</label>
|
||||
<select
|
||||
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"
|
||||
>
|
||||
<option value="">Kategori seçin</option>
|
||||
<option value={OperationCategoryEnum.Production}>Üretim</option>
|
||||
<option value={OperationCategoryEnum.Assembly}>Montaj</option>
|
||||
<option value={OperationCategoryEnum.Inspection}>
|
||||
Kontrol
|
||||
</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>
|
||||
{Object.values(OperationCategoryEnum).map((cat) => (
|
||||
<option key={cat} value={cat}>
|
||||
{getOperationTypeText(cat)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -150,9 +133,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
|||
<input
|
||||
type="number"
|
||||
value={form.defaultDuration}
|
||||
onChange={(e) =>
|
||||
handleChange("defaultDuration", Number(e.target.value))
|
||||
}
|
||||
onChange={(e) => handleChange('defaultDuration', Number(e.target.value))}
|
||||
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -163,9 +144,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
|||
<input
|
||||
type="checkbox"
|
||||
checked={form.requiresSetup}
|
||||
onChange={(e) =>
|
||||
handleChange("requiresSetup", e.target.checked)
|
||||
}
|
||||
onChange={(e) => handleChange('requiresSetup', e.target.checked)}
|
||||
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>
|
||||
|
|
@ -175,9 +154,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
|||
<input
|
||||
type="checkbox"
|
||||
checked={form.allowsParallelOperation}
|
||||
onChange={(e) =>
|
||||
handleChange("allowsParallelOperation", e.target.checked)
|
||||
}
|
||||
onChange={(e) => handleChange('allowsParallelOperation', e.target.checked)}
|
||||
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>
|
||||
|
|
@ -197,13 +174,12 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
|||
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"
|
||||
>
|
||||
<FaSave className="inline mr-2" />{" "}
|
||||
{saving ? "Kaydediliyor..." : "Kaydet"}
|
||||
<FaSave className="inline mr-2" /> {saving ? 'Kaydediliyor...' : 'Kaydet'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default OperationTypeFormModal;
|
||||
export default OperationTypeFormModal
|
||||
|
|
|
|||
|
|
@ -13,12 +13,7 @@ import {
|
|||
import { MrpOperationTypeDefinition } from '../../../types/mrp'
|
||||
import OperationTypeFormModal from './OperationTypeFormModal'
|
||||
import { mockOperationTypes } from '../../../mocks/mockOperationTypes'
|
||||
import {
|
||||
getOperationCategoryColor,
|
||||
getOperationTypeColor,
|
||||
getOperationTypeText,
|
||||
getSkillLevelText,
|
||||
} from '../../../utils/erp'
|
||||
import { getOperationTypeColor, getOperationTypeText, getSkillLevelText } from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
|
||||
const OperationTypes: React.FC = () => {
|
||||
|
|
@ -261,7 +256,7 @@ const OperationTypes: React.FC = () => {
|
|||
</td>
|
||||
<td className="px-3 py-2 whitespace-nowrap">
|
||||
<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,
|
||||
)}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
|
|||
import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
|
||||
import { mockWorkOrders } from '../../../mocks/mockWorkOrders'
|
||||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityColor, getProductionOrderStatus, getWorkOrderStatus } from '../../../utils/erp'
|
||||
import { getFrequencyUnitText, getPriorityColor } from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
import { FrequencyUnitEnum } from '@/types/pm'
|
||||
|
||||
interface PlanningGanttProps {
|
||||
workCenterId?: string
|
||||
|
|
@ -107,7 +107,7 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
|
|||
assignee: wo.assignedOperators[0]
|
||||
? mockEmployees.find((e) => e.id === wo.assignedOperators[0])
|
||||
: undefined,
|
||||
status: getWorkOrderStatus(wo.status),
|
||||
status: wo.status,
|
||||
priority: order.priority,
|
||||
level: 1,
|
||||
children: [],
|
||||
|
|
@ -125,7 +125,7 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
|
|||
order.confirmedQuantity && order.plannedQuantity
|
||||
? Math.round((order.confirmedQuantity / order.plannedQuantity) * 100)
|
||||
: 0,
|
||||
status: getProductionOrderStatus(order.status),
|
||||
status: order.status,
|
||||
priority: order.priority,
|
||||
level: 0,
|
||||
children: workOrders,
|
||||
|
|
@ -480,10 +480,18 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
|
|||
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"
|
||||
>
|
||||
<option value="day">Günlük</option>
|
||||
<option value="week">Haftalık</option>
|
||||
<option value="month">Aylık</option>
|
||||
<option value="year">Yıllık</option>
|
||||
<option value={FrequencyUnitEnum.Days}>
|
||||
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@ import { mockMaterials } from '../../../mocks/mockMaterials'
|
|||
import { PriorityEnum } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import {
|
||||
getPriorityText,
|
||||
getProductionOrderStatusText,
|
||||
getProductionOrderTypeText,
|
||||
} from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
const ProductionOrderForm: React.FC = () => {
|
||||
const { id } = useParams()
|
||||
|
|
@ -260,10 +266,11 @@ const ProductionOrderForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={ProductionOrderTypeEnum.Standard}>Standart</option>
|
||||
<option value={ProductionOrderTypeEnum.Rework}>Yeniden İşleme</option>
|
||||
<option value={ProductionOrderTypeEnum.Maintenance}>Bakım</option>
|
||||
<option value={ProductionOrderTypeEnum.Sample}>Numune</option>
|
||||
{Object.values(ProductionOrderTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getProductionOrderTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -275,12 +282,11 @@ const ProductionOrderForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={ProductionOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={ProductionOrderStatusEnum.Released}>Yayınlandı</option>
|
||||
<option value={ProductionOrderStatusEnum.InProgress}>İşlemde</option>
|
||||
<option value={ProductionOrderStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={ProductionOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
<option value={ProductionOrderStatusEnum.OnHold}>Beklemede</option>
|
||||
{Object.values(ProductionOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getProductionOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -292,10 +298,11 @@ const ProductionOrderForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -469,10 +476,11 @@ const ProductionOrderForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
<option value="GBP">GBP</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={ProductionOrderStatusEnum.Created}>Oluşturuldu</option>
|
||||
<option value={ProductionOrderStatusEnum.Released}>Serbest Bırakıldı</option>
|
||||
<option value={ProductionOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={ProductionOrderStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={ProductionOrderStatusEnum.OnHold}>Beklemede</option>
|
||||
<option value={ProductionOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(ProductionOrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getProductionOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
FaChartBar,
|
||||
FaDownload,
|
||||
} from 'react-icons/fa'
|
||||
import { PsProjectCostTracking } from '../../../types/ps'
|
||||
import { ProjectCostTrackingStatus, PsProjectCostTracking } from '../../../types/ps'
|
||||
import { mockProjectCostTracking } from '../../../mocks/mockProjectCostTracking'
|
||||
import Widget from '../../../components/common/Widget'
|
||||
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"
|
||||
>
|
||||
<option value="">Tüm Durumlar</option>
|
||||
<option value="ON_TRACK">Planında</option>
|
||||
<option value="AT_RISK">Risk Altında</option>
|
||||
<option value="DELAYED">Gecikmiş</option>
|
||||
<option value="COMPLETED">Tamamlandı</option>
|
||||
{Object.values(ProjectCostTrackingStatus).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getCostTimeTrackingStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,22 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
FaPlus,
|
||||
FaEdit,
|
||||
FaSave,
|
||||
FaTimesCircle,
|
||||
FaProjectDiagram,
|
||||
} from "react-icons/fa";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FaPlus, FaEdit, FaSave, FaTimesCircle, FaProjectDiagram } from 'react-icons/fa'
|
||||
import {
|
||||
PhaseStatusEnum,
|
||||
PsProjectPhase,
|
||||
ProjectStatusEnum,
|
||||
} from "../../../types/ps";
|
||||
import { mockProjects } from "../../../mocks/mockProjects";
|
||||
import { mockProjectPhases } from "../../../mocks/mockProjectPhases";
|
||||
import MultiSelectTeam from "../../../components/common/MultiSelectTeam";
|
||||
PhaseCategoryEnum,
|
||||
} from '../../../types/ps'
|
||||
import { mockProjects } from '../../../mocks/mockProjects'
|
||||
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||
import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
|
||||
import { getPhaseCategoryText, getPhaseStatusText } from '@/utils/erp'
|
||||
|
||||
interface PhaseEditModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
phase?: PsProjectPhase | null;
|
||||
defaultProjectId?: string;
|
||||
onSubmit: (data: PsProjectPhase) => void;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
phase?: PsProjectPhase | null
|
||||
defaultProjectId?: string
|
||||
onSubmit: (data: PsProjectPhase) => void
|
||||
}
|
||||
|
||||
const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||
|
|
@ -30,14 +26,14 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
defaultProjectId,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const isEdit = Boolean(phase);
|
||||
const isEdit = Boolean(phase)
|
||||
|
||||
const ProjectPhaseNew: PsProjectPhase = {
|
||||
id: "",
|
||||
projectId: defaultProjectId || "",
|
||||
code: "",
|
||||
name: "",
|
||||
description: "",
|
||||
id: '',
|
||||
projectId: defaultProjectId || '',
|
||||
code: '',
|
||||
name: '',
|
||||
description: '',
|
||||
sequence: 0,
|
||||
startDate: new Date(),
|
||||
endDate: new Date(),
|
||||
|
|
@ -52,10 +48,10 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
assignedTeams: [],
|
||||
deliverables: [],
|
||||
risks: [],
|
||||
category: "",
|
||||
};
|
||||
category: PhaseCategoryEnum.Planning,
|
||||
}
|
||||
|
||||
const [formData, setFormData] = useState<PsProjectPhase>(ProjectPhaseNew);
|
||||
const [formData, setFormData] = useState<PsProjectPhase>(ProjectPhaseNew)
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
|
|
@ -66,50 +62,48 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
name: phase.name,
|
||||
projectId: phase.projectId,
|
||||
code: phase.code,
|
||||
description: phase.description || "",
|
||||
description: phase.description || '',
|
||||
status: phase.status,
|
||||
startDate: phase.startDate,
|
||||
endDate: phase.endDate,
|
||||
budget: phase.budget,
|
||||
category: phase.category,
|
||||
assignedTeams: phase.assignedTeams || [],
|
||||
});
|
||||
})
|
||||
} else {
|
||||
setFormData(ProjectPhaseNew);
|
||||
setFormData(ProjectPhaseNew)
|
||||
}
|
||||
}
|
||||
}, [isOpen, phase, defaultProjectId]);
|
||||
}, [isOpen, phase, defaultProjectId])
|
||||
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<
|
||||
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
||||
>
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
|
||||
) => {
|
||||
const { name, value } = e.target;
|
||||
const { name, value } = e.target
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const handleTeamChange = (teams: string[]) => {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
assignedTeams: teams,
|
||||
}));
|
||||
};
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
onSubmit(formData);
|
||||
};
|
||||
e.preventDefault()
|
||||
onSubmit(formData)
|
||||
}
|
||||
|
||||
const generatePhaseCode = () => {
|
||||
const phaseCount = mockProjectPhases.length + 1;
|
||||
return `PH-${phaseCount.toString().padStart(3, "0")}`;
|
||||
};
|
||||
const phaseCount = mockProjectPhases.length + 1
|
||||
return `PH-${phaseCount.toString().padStart(3, '0')}`
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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>
|
||||
<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>
|
||||
<p className="text-xs text-gray-600">
|
||||
{isEdit
|
||||
? "Mevcut aşama bilgilerini güncelleyin"
|
||||
: "Yeni bir proje aşaması tanımlayın"}
|
||||
? 'Mevcut aşama bilgilerini güncelleyin'
|
||||
: 'Yeni bir proje aşaması tanımlayın'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -179,9 +173,9 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
{formData.projectId &&
|
||||
(() => {
|
||||
const selectedProject = mockProjects.find(
|
||||
(p) => p.id === formData.projectId
|
||||
);
|
||||
if (!selectedProject) return null;
|
||||
(p) => p.id === formData.projectId,
|
||||
)
|
||||
if (!selectedProject) return null
|
||||
|
||||
return (
|
||||
<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>
|
||||
<div className="grid grid-cols-2 gap-1.5 text-xs">
|
||||
<div>
|
||||
<span className="font-medium text-blue-800">
|
||||
Durum:
|
||||
</span>
|
||||
<span className="font-medium text-blue-800">Durum:</span>
|
||||
<span
|
||||
className={`ml-1 px-1.5 py-0.5 rounded-full text-xs font-medium ${
|
||||
selectedProject.status ===
|
||||
ProjectStatusEnum.Active
|
||||
? "bg-green-100 text-green-800"
|
||||
: selectedProject.status ===
|
||||
ProjectStatusEnum.Planning
|
||||
? "bg-yellow-100 text-yellow-800"
|
||||
: "bg-gray-100 text-gray-800"
|
||||
selectedProject.status === ProjectStatusEnum.Active
|
||||
? 'bg-green-100 text-green-800'
|
||||
: selectedProject.status === ProjectStatusEnum.Planning
|
||||
? 'bg-yellow-100 text-yellow-800'
|
||||
: 'bg-gray-100 text-gray-800'
|
||||
}`}
|
||||
>
|
||||
{selectedProject.status ===
|
||||
ProjectStatusEnum.Active
|
||||
? "Aktif"
|
||||
: selectedProject.status ===
|
||||
ProjectStatusEnum.Planning
|
||||
? "Planlama"
|
||||
: selectedProject.status ===
|
||||
ProjectStatusEnum.Completed
|
||||
? "Tamamlandı"
|
||||
: selectedProject.status ===
|
||||
ProjectStatusEnum.OnHold
|
||||
? "Beklemede"
|
||||
: "İptal"}
|
||||
{selectedProject.status === ProjectStatusEnum.Active
|
||||
? 'Aktif'
|
||||
: selectedProject.status === ProjectStatusEnum.Planning
|
||||
? 'Planlama'
|
||||
: selectedProject.status === ProjectStatusEnum.Completed
|
||||
? 'Tamamlandı'
|
||||
: selectedProject.status === ProjectStatusEnum.OnHold
|
||||
? 'Beklemede'
|
||||
: 'İptal'}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium text-blue-800">
|
||||
İlerleme:
|
||||
</span>
|
||||
<span className="font-medium text-blue-800">İlerleme:</span>
|
||||
<span className="ml-1 text-blue-700">
|
||||
%{selectedProject.progress}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium text-blue-800">
|
||||
Başlangıç:
|
||||
</span>
|
||||
<span className="font-medium text-blue-800">Başlangıç:</span>
|
||||
<span className="ml-1 text-blue-700">
|
||||
{selectedProject.startDate.toLocaleDateString(
|
||||
"tr-TR"
|
||||
)}
|
||||
{selectedProject.startDate.toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium text-blue-800">
|
||||
Bitiş:
|
||||
</span>
|
||||
<span className="font-medium text-blue-800">Bitiş:</span>
|
||||
<span className="ml-1 text-blue-700">
|
||||
{selectedProject.endDate.toLocaleDateString(
|
||||
"tr-TR"
|
||||
)}
|
||||
{selectedProject.endDate.toLocaleDateString('tr-TR')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-1.5 text-right">
|
||||
<div className="text-base font-bold text-blue-900">
|
||||
₺
|
||||
{selectedProject.budget.toLocaleString(
|
||||
"tr-TR"
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-blue-700">
|
||||
Bütçe
|
||||
₺{selectedProject.budget.toLocaleString('tr-TR')}
|
||||
</div>
|
||||
<div className="text-xs text-blue-700">Bütçe</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
|
||||
|
|
@ -287,9 +258,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Açıklama
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama</label>
|
||||
<textarea
|
||||
name="description"
|
||||
value={formData.description}
|
||||
|
|
@ -302,30 +271,18 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Durum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||
<select
|
||||
name="status"
|
||||
value={formData.status}
|
||||
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"
|
||||
>
|
||||
<option value={PhaseStatusEnum.NotStarted}>
|
||||
Başlanmadı
|
||||
</option>
|
||||
<option value={PhaseStatusEnum.InProgress}>
|
||||
Devam Ediyor
|
||||
</option>
|
||||
<option value={PhaseStatusEnum.Completed}>
|
||||
Tamamlandı
|
||||
</option>
|
||||
<option value={PhaseStatusEnum.OnHold}>
|
||||
Beklemede
|
||||
</option>
|
||||
<option value={PhaseStatusEnum.Cancelled}>
|
||||
İptal Edildi
|
||||
</option>
|
||||
{Object.values(PhaseStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getPhaseStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Kategori seçin...</option>
|
||||
<option value="Planning">Planlama</option>
|
||||
<option value="Development">Geliştirme</option>
|
||||
<option value="Testing">Test</option>
|
||||
<option value="Deployment">Dağıtım</option>
|
||||
<option value="Design">Tasarım</option>
|
||||
{Object.values(PhaseCategoryEnum).map((cat) => (
|
||||
<option key={cat} value={cat}>
|
||||
{getPhaseCategoryText(cat)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -369,7 +326,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
<input
|
||||
type="date"
|
||||
name="startDate"
|
||||
value={formData.startDate.toISOString().split("T")[0]}
|
||||
value={formData.startDate.toISOString().split('T')[0]}
|
||||
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"
|
||||
/>
|
||||
|
|
@ -382,7 +339,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
<input
|
||||
type="date"
|
||||
name="endDate"
|
||||
value={formData.endDate.toISOString().split("T")[0]}
|
||||
value={formData.endDate.toISOString().split('T')[0]}
|
||||
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"
|
||||
/>
|
||||
|
|
@ -426,9 +383,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
|||
<div className="flex items-center gap-2 text-blue-800">
|
||||
<FaProjectDiagram className="w-4 h-4" />
|
||||
<span className="text-sm font-medium">Aşama Kodu:</span>
|
||||
<span className="font-bold">
|
||||
{isEdit ? phase?.code : generatePhaseCode()}
|
||||
</span>
|
||||
<span className="font-bold">{isEdit ? phase?.code : generatePhaseCode()}</span>
|
||||
</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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{isEdit ? "Güncelle" : "Oluştur"}
|
||||
{isEdit ? 'Güncelle' : 'Oluştur'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default PhaseEditModal;
|
||||
export default PhaseEditModal
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ import {
|
|||
} from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
// Custom styles for the slider
|
||||
const sliderStyles = `
|
||||
|
|
@ -810,10 +811,11 @@ const ProjectForm: React.FC = () => {
|
|||
}`}
|
||||
>
|
||||
<option value="">Tip seçin</option>
|
||||
<option value="INTERNAL">İç Proje</option>
|
||||
<option value="CUSTOMER">Müşteri Projesi</option>
|
||||
<option value="RESEARCH">Ar-Ge Projesi</option>
|
||||
<option value="MAINTENANCE">Bakım Projesi</option>
|
||||
{Object.values(ProjectTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getProjectTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.projectType && (
|
||||
<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)}
|
||||
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>
|
||||
<option value="ACTIVE">Aktif</option>
|
||||
<option value="ON_HOLD">Beklemede</option>
|
||||
<option value="COMPLETED">Tamamlandı</option>
|
||||
<option value="CANCELLED">İptal Edildi</option>
|
||||
{Object.values(ProjectStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getProjectStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -868,10 +870,11 @@ const ProjectForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="LOW">Düşük</option>
|
||||
<option value="NORMAL">Normal</option>
|
||||
<option value="HIGH">Yüksek</option>
|
||||
<option value="URGENT">Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{priority}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -884,9 +887,11 @@ const ProjectForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">Türk Lirası (TRY)</option>
|
||||
<option value="USD">Amerikan Doları (USD)</option>
|
||||
<option value="EUR">Euro (EUR)</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1238,9 +1243,11 @@ const ProjectForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">Türk Lirası (TRY)</option>
|
||||
<option value="USD">Amerikan Doları (USD)</option>
|
||||
<option value="EUR">Euro (EUR)</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ import { mockProjects } from '../../../mocks/mockProjects'
|
|||
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||
import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityColor, getProjectStatusColor } from '../../../utils/erp'
|
||||
import { getFrequencyUnitText, getGanttStatusColor, getPriorityColor } from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
import { FrequencyUnitEnum } from '@/types/pm'
|
||||
|
||||
interface ProjectGanttProps {
|
||||
employeeId?: string
|
||||
|
|
@ -479,7 +480,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
|||
if (task.type === 'task' && position.isVisible) {
|
||||
return (
|
||||
<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,
|
||||
)} shadow-md group cursor-pointer border border-white border-opacity-20`}
|
||||
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>
|
||||
<h2 className="text-2xl font-bold text-gray-900">İş Yükü ve Proje Takibi</h2>
|
||||
<p className="text-gray-600">
|
||||
Tüm görevlerinizi merkezi bir noktadan yönetin.
|
||||
</p>
|
||||
<p className="text-gray-600">Tüm görevlerinizi merkezi bir noktadan yönetin.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -592,7 +591,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
|||
<option value="">Tüm Çalışanlar</option>
|
||||
{mockEmployees.map((emp) => (
|
||||
<option key={emp.id} value={emp.id}>
|
||||
{emp.firstName} {emp.lastName}
|
||||
{emp.fullName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
|
@ -602,10 +601,18 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
|||
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"
|
||||
>
|
||||
<option value="day">Günlük</option>
|
||||
<option value="week">Haftalık</option>
|
||||
<option value="month">Aylık</option>
|
||||
<option value="year">Yıllık</option>
|
||||
<option value={FrequencyUnitEnum.Days}>
|
||||
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={ProjectStatusEnum.Planning}>Planlama</option>
|
||||
<option value={ProjectStatusEnum.Active}>Aktif</option>
|
||||
<option value={ProjectStatusEnum.OnHold}>Beklemede</option>
|
||||
<option value={ProjectStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={ProjectStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(ProjectStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getProjectStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@ import {
|
|||
FaSave,
|
||||
FaProjectDiagram,
|
||||
} 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 { mockProjects } from '../../../mocks/mockProjects'
|
||||
import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
|
||||
|
|
@ -23,6 +28,8 @@ import {
|
|||
getPhaseStatusIcon,
|
||||
getPhaseStatusText,
|
||||
getPhaseStatusColor,
|
||||
getProjectStatusText,
|
||||
getPhaseCategoryText,
|
||||
} from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
|
||||
|
|
@ -45,7 +52,7 @@ const ProjectPhases: React.FC = () => {
|
|||
startDate: '',
|
||||
endDate: '',
|
||||
budget: 0,
|
||||
category: '',
|
||||
category: PhaseCategoryEnum.Planning,
|
||||
assignedTeams: [] as string[],
|
||||
})
|
||||
|
||||
|
|
@ -93,7 +100,7 @@ const ProjectPhases: React.FC = () => {
|
|||
startDate: '',
|
||||
endDate: '',
|
||||
budget: 0,
|
||||
category: '',
|
||||
category: PhaseCategoryEnum.Planning,
|
||||
assignedTeams: [],
|
||||
})
|
||||
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"
|
||||
>
|
||||
<option value="All">Tüm Durumlar</option>
|
||||
<option value={ProjectStatusEnum.Planning}>Başlanmadı</option>
|
||||
<option value={ProjectStatusEnum.Active}>Devam Ediyor</option>
|
||||
<option value={ProjectStatusEnum.OnHold}>Beklemede</option>
|
||||
<option value={ProjectStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={ProjectStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(ProjectStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getProjectStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="">Kategori seçin...</option>
|
||||
<option value="Planning">Planlama</option>
|
||||
<option value="Development">Geliştirme</option>
|
||||
<option value="Testing">Test</option>
|
||||
<option value="Deployment">Dağıtım</option>
|
||||
<option value="Design">Tasarım</option>
|
||||
{Object.values(PhaseCategoryEnum).map((cat) => (
|
||||
<option key={cat} value={cat}>
|
||||
{getPhaseCategoryText(cat)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -880,11 +887,11 @@ const ProjectPhases: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={PhaseStatusEnum.NotStarted}>Başlanmadı</option>
|
||||
<option value={PhaseStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={PhaseStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={PhaseStatusEnum.OnHold}>Beklemede</option>
|
||||
<option value={PhaseStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(PhaseStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getPhaseStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from "../../../types/ps";
|
||||
import React, { useState } from 'react'
|
||||
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from '../../../types/ps'
|
||||
import {
|
||||
FaSearch,
|
||||
FaPlus,
|
||||
|
|
@ -13,158 +13,157 @@ import {
|
|||
FaFlag,
|
||||
FaProjectDiagram,
|
||||
FaUserCog,
|
||||
} from "react-icons/fa";
|
||||
import { mockProjectTasks } from "../../../mocks/mockProjectTasks";
|
||||
import { mockEmployees } from "../../../mocks/mockEmployees";
|
||||
import { mockProjects } from "../../../mocks/mockProjects";
|
||||
import { mockProjectPhases } from "../../../mocks/mockProjectPhases";
|
||||
import Widget from "../../../components/common/Widget";
|
||||
import { PriorityEnum } from "../../../types/common";
|
||||
} from 'react-icons/fa'
|
||||
import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { mockProjects } from '../../../mocks/mockProjects'
|
||||
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||
import Widget from '../../../components/common/Widget'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import {
|
||||
getTaskStatusColor,
|
||||
getTaskStatusIcon,
|
||||
getPriorityColor,
|
||||
getTaskTypeColor,
|
||||
} from "../../../utils/erp";
|
||||
import { Container } from "@/components/shared";
|
||||
getPriorityText,
|
||||
getTaskStatusText,
|
||||
getTaskTypeText,
|
||||
} from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
|
||||
const ProjectTasks: React.FC = () => {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [statusFilter, setStatusFilter] = useState<TaskStatusEnum | "">("");
|
||||
const [selectedProjectFilter, setSelectedProjectFilter] = useState("All");
|
||||
const [selectedTask, setSelectedTask] = useState<PsProjectTask | null>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [editingTask, setEditingTask] = useState<PsProjectTask | null>(null);
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [statusFilter, setStatusFilter] = useState<TaskStatusEnum | ''>('')
|
||||
const [selectedProjectFilter, setSelectedProjectFilter] = useState('All')
|
||||
const [selectedTask, setSelectedTask] = useState<PsProjectTask | null>(null)
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false)
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false)
|
||||
const [editingTask, setEditingTask] = useState<PsProjectTask | null>(null)
|
||||
|
||||
// Form state for creating/editing tasks
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
description: "",
|
||||
projectId: "",
|
||||
phaseId: "",
|
||||
name: '',
|
||||
description: '',
|
||||
projectId: '',
|
||||
phaseId: '',
|
||||
taskType: TaskTypeEnum.Development,
|
||||
status: TaskStatusEnum.NotStarted,
|
||||
priority: PriorityEnum.Normal,
|
||||
assignedTo: "",
|
||||
assigneeEmail: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
assignedTo: '',
|
||||
assigneeEmail: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
estimatedHours: 0,
|
||||
progress: 0,
|
||||
});
|
||||
})
|
||||
|
||||
const filteredTasks = mockProjectTasks.filter((task) => {
|
||||
const matchesSearch =
|
||||
task.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
task.taskCode.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
(task.description &&
|
||||
task.description.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
const matchesStatus = statusFilter === "" || task.status === statusFilter;
|
||||
(task.description && task.description.toLowerCase().includes(searchTerm.toLowerCase()))
|
||||
const matchesStatus = statusFilter === '' || task.status === statusFilter
|
||||
const matchesProject =
|
||||
selectedProjectFilter === "All" ||
|
||||
task.projectId === selectedProjectFilter;
|
||||
return matchesSearch && matchesStatus && matchesProject;
|
||||
});
|
||||
selectedProjectFilter === 'All' || task.projectId === selectedProjectFilter
|
||||
return matchesSearch && matchesStatus && matchesProject
|
||||
})
|
||||
|
||||
const openModal = (task: PsProjectTask) => {
|
||||
setSelectedTask(task);
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
setSelectedTask(task)
|
||||
setIsModalOpen(true)
|
||||
}
|
||||
|
||||
const closeModal = () => {
|
||||
setSelectedTask(null);
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
setSelectedTask(null)
|
||||
setIsModalOpen(false)
|
||||
}
|
||||
|
||||
const openCreateModal = () => {
|
||||
setFormData({
|
||||
name: "",
|
||||
description: "",
|
||||
projectId: "",
|
||||
phaseId: "",
|
||||
name: '',
|
||||
description: '',
|
||||
projectId: '',
|
||||
phaseId: '',
|
||||
taskType: TaskTypeEnum.Development,
|
||||
status: TaskStatusEnum.NotStarted,
|
||||
priority: PriorityEnum.Normal,
|
||||
assignedTo: "",
|
||||
assigneeEmail: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
assignedTo: '',
|
||||
assigneeEmail: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
estimatedHours: 0,
|
||||
progress: 0,
|
||||
});
|
||||
setIsCreateModalOpen(true);
|
||||
};
|
||||
})
|
||||
setIsCreateModalOpen(true)
|
||||
}
|
||||
|
||||
const closeCreateModal = () => {
|
||||
setIsCreateModalOpen(false);
|
||||
};
|
||||
setIsCreateModalOpen(false)
|
||||
}
|
||||
|
||||
const openEditModal = (task: PsProjectTask) => {
|
||||
setEditingTask(task);
|
||||
setEditingTask(task)
|
||||
setFormData({
|
||||
name: task.name,
|
||||
description: task.description || "",
|
||||
projectId: task.projectId || "",
|
||||
phaseId: task.phaseId || "",
|
||||
description: task.description || '',
|
||||
projectId: task.projectId || '',
|
||||
phaseId: task.phaseId || '',
|
||||
taskType: task.taskType,
|
||||
status: task.status,
|
||||
priority: task.priority,
|
||||
assignedTo: task.assignedTo || "",
|
||||
assigneeEmail: task.assignee?.email || "",
|
||||
startDate: task.startDate.toISOString().split("T")[0],
|
||||
endDate: task.endDate.toISOString().split("T")[0],
|
||||
assignedTo: task.assignedTo || '',
|
||||
assigneeEmail: task.assignee?.email || '',
|
||||
startDate: task.startDate.toISOString().split('T')[0],
|
||||
endDate: task.endDate.toISOString().split('T')[0],
|
||||
estimatedHours: task.estimatedHours,
|
||||
progress: task.progress,
|
||||
});
|
||||
setIsEditModalOpen(true);
|
||||
};
|
||||
})
|
||||
setIsEditModalOpen(true)
|
||||
}
|
||||
|
||||
const closeEditModal = () => {
|
||||
setIsEditModalOpen(false);
|
||||
setEditingTask(null);
|
||||
};
|
||||
setIsEditModalOpen(false)
|
||||
setEditingTask(null)
|
||||
}
|
||||
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<
|
||||
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
||||
>
|
||||
e: React.ChangeEvent<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
|
||||
if (name === "assignedTo") {
|
||||
const selectedEmployee = mockEmployees.find((emp) => emp.id === value);
|
||||
if (name === 'assignedTo') {
|
||||
const selectedEmployee = mockEmployees.find((emp) => emp.id === value)
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
assigneeEmail: selectedEmployee?.email || "",
|
||||
}));
|
||||
assigneeEmail: selectedEmployee?.email || '',
|
||||
}))
|
||||
} else {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
}));
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
// Here you would normally save to backend
|
||||
console.log("Saving task:", formData);
|
||||
alert(isEditModalOpen ? "Görev güncellendi!" : "Yeni görev oluşturuldu!");
|
||||
console.log('Saving task:', formData)
|
||||
alert(isEditModalOpen ? 'Görev güncellendi!' : 'Yeni görev oluşturuldu!')
|
||||
if (isEditModalOpen) {
|
||||
closeEditModal();
|
||||
closeEditModal()
|
||||
} else {
|
||||
closeCreateModal();
|
||||
closeCreateModal()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const generateTaskCode = () => {
|
||||
const taskCount = mockProjectTasks.length + 1;
|
||||
return `TSK-${taskCount.toString().padStart(3, "0")}`;
|
||||
};
|
||||
const taskCount = mockProjectTasks.length + 1
|
||||
return `TSK-${taskCount.toString().padStart(3, '0')}`
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
|
@ -172,9 +171,7 @@ const ProjectTasks: React.FC = () => {
|
|||
<div className="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-gray-900">Görev Yönetimi</h2>
|
||||
<p className="text-gray-600">
|
||||
Proje görevlerinizi oluşturun, düzenleyin ve takip edin
|
||||
</p>
|
||||
<p className="text-gray-600">Proje görevlerinizi oluşturun, düzenleyin ve takip edin</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={openCreateModal}
|
||||
|
|
@ -196,22 +193,14 @@ const ProjectTasks: React.FC = () => {
|
|||
|
||||
<Widget
|
||||
title="Devam Eden"
|
||||
value={
|
||||
mockProjectTasks.filter(
|
||||
(t) => t.status === TaskStatusEnum.InProgress
|
||||
).length
|
||||
}
|
||||
value={mockProjectTasks.filter((t) => t.status === TaskStatusEnum.InProgress).length}
|
||||
color="yellow"
|
||||
icon="FaClock"
|
||||
/>
|
||||
|
||||
<Widget
|
||||
title="Tamamlanan"
|
||||
value={
|
||||
mockProjectTasks.filter(
|
||||
(t) => t.status === TaskStatusEnum.Completed
|
||||
).length
|
||||
}
|
||||
value={mockProjectTasks.filter((t) => t.status === TaskStatusEnum.Completed).length}
|
||||
color="green"
|
||||
icon="FaCheckCircle"
|
||||
/>
|
||||
|
|
@ -222,9 +211,9 @@ const ProjectTasks: React.FC = () => {
|
|||
mockProjectTasks.length > 0
|
||||
? `${Math.round(
|
||||
mockProjectTasks.reduce((sum, t) => sum + t.progress, 0) /
|
||||
mockProjectTasks.length
|
||||
mockProjectTasks.length,
|
||||
)}%`
|
||||
: "0%"
|
||||
: '0%'
|
||||
}
|
||||
color="red"
|
||||
icon="FaBullseye"
|
||||
|
|
@ -260,17 +249,15 @@ const ProjectTasks: React.FC = () => {
|
|||
|
||||
<select
|
||||
value={statusFilter}
|
||||
onChange={(e) =>
|
||||
setStatusFilter(e.target.value as TaskStatusEnum | "")
|
||||
}
|
||||
onChange={(e) => 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"
|
||||
>
|
||||
<option value="">Tüm Durumlar</option>
|
||||
<option value={TaskStatusEnum.NotStarted}>Başlanmadı</option>
|
||||
<option value={TaskStatusEnum.InProgress}>Devam Ediyor</option>
|
||||
<option value={TaskStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={TaskStatusEnum.OnHold}>Beklemede</option>
|
||||
<option value={TaskStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(TaskStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getTaskStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -316,25 +303,21 @@ const ProjectTasks: React.FC = () => {
|
|||
<tr
|
||||
key={task.id}
|
||||
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">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-blue-700">
|
||||
{(() => {
|
||||
const project = mockProjects.find(
|
||||
(p) => p.id === task.projectId
|
||||
);
|
||||
return project?.name || `Proje ID: ${task.projectId}`;
|
||||
const project = mockProjects.find((p) => p.id === task.projectId)
|
||||
return project?.name || `Proje ID: ${task.projectId}`
|
||||
})()}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">
|
||||
{(() => {
|
||||
const project = mockProjects.find(
|
||||
(p) => p.id === task.projectId
|
||||
);
|
||||
return project?.code || task.projectId;
|
||||
const project = mockProjects.find((p) => p.id === task.projectId)
|
||||
return project?.code || task.projectId
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -344,19 +327,15 @@ const ProjectTasks: React.FC = () => {
|
|||
<div className="text-sm font-medium text-green-700">
|
||||
{task.phase?.name ||
|
||||
(() => {
|
||||
const phase = mockProjectPhases.find(
|
||||
(p) => p.id === task.phaseId
|
||||
);
|
||||
return phase?.name || `Aşama ID: ${task.phaseId}`;
|
||||
const phase = mockProjectPhases.find((p) => p.id === task.phaseId)
|
||||
return phase?.name || `Aşama ID: ${task.phaseId}`
|
||||
})()}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">
|
||||
{task.phase?.code ||
|
||||
(() => {
|
||||
const phase = mockProjectPhases.find(
|
||||
(p) => p.id === task.phaseId
|
||||
);
|
||||
return phase?.code || task.phaseId;
|
||||
const phase = mockProjectPhases.find((p) => p.id === task.phaseId)
|
||||
return phase?.code || task.phaseId
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -375,7 +354,7 @@ const ProjectTasks: React.FC = () => {
|
|||
<td className="px-2 py-1 whitespace-nowrap">
|
||||
<span
|
||||
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)}
|
||||
|
|
@ -385,7 +364,7 @@ const ProjectTasks: React.FC = () => {
|
|||
<td className="px-2 py-1 whitespace-nowrap">
|
||||
<span
|
||||
className={`inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-semibold ${getPriorityColor(
|
||||
task.priority
|
||||
task.priority,
|
||||
)}`}
|
||||
>
|
||||
{task.priority}
|
||||
|
|
@ -397,7 +376,7 @@ const ProjectTasks: React.FC = () => {
|
|||
<FaUser className="w-4 h-4 text-blue-600" />
|
||||
</div>
|
||||
<div className="text-sm text-gray-900 font-medium">
|
||||
{task.assignee?.fullName || "-"}
|
||||
{task.assignee?.fullName || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
|
@ -415,7 +394,7 @@ const ProjectTasks: React.FC = () => {
|
|||
</div>
|
||||
</td>
|
||||
<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 className="px-2 py-1 whitespace-nowrap text-sm font-medium">
|
||||
<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">
|
||||
<FaBullseye className="w-6 h-6 text-gray-400" />
|
||||
</div>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-1">
|
||||
Görev bulunamadı
|
||||
</h3>
|
||||
<h3 className="text-base font-medium text-gray-900 mb-1">Görev bulunamadı</h3>
|
||||
<p className="text-gray-500">
|
||||
Arama kriterlerinizi değiştirmeyi deneyin veya yeni bir görev
|
||||
oluşturun.
|
||||
Arama kriterlerinizi değiştirmeyi deneyin veya yeni bir görev oluşturun.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -500,20 +476,17 @@ const ProjectTasks: React.FC = () => {
|
|||
<div className="text-sm font-semibold text-blue-800">
|
||||
{(() => {
|
||||
const project = mockProjects.find(
|
||||
(p) => p.id === selectedTask.projectId
|
||||
);
|
||||
return (
|
||||
project?.name ||
|
||||
`Proje ID: ${selectedTask.projectId}`
|
||||
);
|
||||
(p) => p.id === selectedTask.projectId,
|
||||
)
|
||||
return project?.name || `Proje ID: ${selectedTask.projectId}`
|
||||
})()}
|
||||
</div>
|
||||
<div className="text-xs text-blue-600 mt-1">
|
||||
{(() => {
|
||||
const project = mockProjects.find(
|
||||
(p) => p.id === selectedTask.projectId
|
||||
);
|
||||
return project?.code || selectedTask.projectId;
|
||||
(p) => p.id === selectedTask.projectId,
|
||||
)
|
||||
return project?.code || selectedTask.projectId
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -528,21 +501,18 @@ const ProjectTasks: React.FC = () => {
|
|||
{selectedTask.phase?.name ||
|
||||
(() => {
|
||||
const phase = mockProjectPhases.find(
|
||||
(p) => p.id === selectedTask.phaseId
|
||||
);
|
||||
return (
|
||||
phase?.name ||
|
||||
`Aşama ID: ${selectedTask.phaseId}`
|
||||
);
|
||||
(p) => p.id === selectedTask.phaseId,
|
||||
)
|
||||
return phase?.name || `Aşama ID: ${selectedTask.phaseId}`
|
||||
})()}
|
||||
</div>
|
||||
<div className="text-xs text-green-600 mt-1">
|
||||
{selectedTask.phase?.code ||
|
||||
(() => {
|
||||
const phase = mockProjectPhases.find(
|
||||
(p) => p.id === selectedTask.phaseId
|
||||
);
|
||||
return phase?.code || selectedTask.phaseId;
|
||||
(p) => p.id === selectedTask.phaseId,
|
||||
)
|
||||
return phase?.code || selectedTask.phaseId
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -554,7 +524,7 @@ const ProjectTasks: React.FC = () => {
|
|||
Açıklama
|
||||
</label>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
|
@ -565,7 +535,7 @@ const ProjectTasks: React.FC = () => {
|
|||
</label>
|
||||
<span
|
||||
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getTaskTypeColor(
|
||||
selectedTask.taskType
|
||||
selectedTask.taskType,
|
||||
)}`}
|
||||
>
|
||||
{selectedTask.taskType}
|
||||
|
|
@ -577,7 +547,7 @@ const ProjectTasks: React.FC = () => {
|
|||
</label>
|
||||
<span
|
||||
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)}
|
||||
|
|
@ -592,7 +562,7 @@ const ProjectTasks: React.FC = () => {
|
|||
</label>
|
||||
<span
|
||||
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getPriorityColor(
|
||||
selectedTask.priority
|
||||
selectedTask.priority,
|
||||
)}`}
|
||||
>
|
||||
{selectedTask.priority}
|
||||
|
|
@ -612,9 +582,7 @@ const ProjectTasks: React.FC = () => {
|
|||
<p className="text-sm font-medium text-gray-900">
|
||||
{selectedTask.assignee.fullName}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
{selectedTask.assignee.email}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">{selectedTask.assignee.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -641,7 +609,7 @@ const ProjectTasks: React.FC = () => {
|
|||
Planlanan Başlangıç
|
||||
</label>
|
||||
<p className="text-sm text-gray-900 font-medium">
|
||||
{selectedTask.startDate.toLocaleDateString("tr-TR")}
|
||||
{selectedTask.startDate.toLocaleDateString('tr-TR')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white p-2 rounded-lg border">
|
||||
|
|
@ -649,9 +617,8 @@ const ProjectTasks: React.FC = () => {
|
|||
Gerçek Başlangıç
|
||||
</label>
|
||||
<p className="text-sm text-gray-900 font-medium">
|
||||
{selectedTask.actualStartDate?.toLocaleDateString(
|
||||
"tr-TR"
|
||||
) || "Henüz başlanmadı"}
|
||||
{selectedTask.actualStartDate?.toLocaleDateString('tr-TR') ||
|
||||
'Henüz başlanmadı'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -662,7 +629,7 @@ const ProjectTasks: React.FC = () => {
|
|||
Planlanan Bitiş
|
||||
</label>
|
||||
<p className="text-sm text-gray-900 font-medium">
|
||||
{selectedTask.endDate.toLocaleDateString("tr-TR")}
|
||||
{selectedTask.endDate.toLocaleDateString('tr-TR')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white p-2 rounded-lg border">
|
||||
|
|
@ -670,9 +637,8 @@ const ProjectTasks: React.FC = () => {
|
|||
Gerçek Bitiş
|
||||
</label>
|
||||
<p className="text-sm text-gray-900 font-medium">
|
||||
{selectedTask.actualEndDate?.toLocaleDateString(
|
||||
"tr-TR"
|
||||
) || "Henüz tamamlanmadı"}
|
||||
{selectedTask.actualEndDate?.toLocaleDateString('tr-TR') ||
|
||||
'Henüz tamamlanmadı'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -727,9 +693,7 @@ const ProjectTasks: React.FC = () => {
|
|||
Oluşturulma
|
||||
</label>
|
||||
<p className="text-sm text-gray-500">
|
||||
{selectedTask.creationTime.toLocaleDateString(
|
||||
"tr-TR"
|
||||
)}
|
||||
{selectedTask.creationTime.toLocaleDateString('tr-TR')}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -737,9 +701,7 @@ const ProjectTasks: React.FC = () => {
|
|||
Son Güncelleme
|
||||
</label>
|
||||
<p className="text-sm text-gray-500">
|
||||
{selectedTask.lastModificationTime.toLocaleDateString(
|
||||
"tr-TR"
|
||||
)}
|
||||
{selectedTask.lastModificationTime.toLocaleDateString('tr-TR')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -759,8 +721,8 @@ const ProjectTasks: React.FC = () => {
|
|||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
closeModal();
|
||||
openEditModal(selectedTask!);
|
||||
closeModal()
|
||||
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"
|
||||
>
|
||||
|
|
@ -788,12 +750,12 @@ const ProjectTasks: React.FC = () => {
|
|||
</div>
|
||||
<div>
|
||||
<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>
|
||||
<p className="text-xs text-gray-600">
|
||||
{isEditModalOpen
|
||||
? "Mevcut görev bilgilerini güncelleyin"
|
||||
: "Yeni bir görev tanımlayın"}
|
||||
? 'Mevcut görev bilgilerini güncelleyin'
|
||||
: 'Yeni bir görev tanımlayın'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -850,16 +812,11 @@ const ProjectTasks: React.FC = () => {
|
|||
disabled={!formData.projectId}
|
||||
>
|
||||
<option value="">
|
||||
{formData.projectId
|
||||
? "Aşama seçin..."
|
||||
: "Önce proje seçin"}
|
||||
{formData.projectId ? 'Aşama seçin...' : 'Önce proje seçin'}
|
||||
</option>
|
||||
{formData.projectId &&
|
||||
mockProjectPhases
|
||||
.filter(
|
||||
(phase) =>
|
||||
phase.projectId === formData.projectId
|
||||
)
|
||||
.filter((phase) => phase.projectId === formData.projectId)
|
||||
.map((phase) => (
|
||||
<option key={phase.id} value={phase.id}>
|
||||
{phase.code} - {phase.name}
|
||||
|
|
@ -907,18 +864,11 @@ const ProjectTasks: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={TaskTypeEnum.Development}>
|
||||
Geliştirme
|
||||
</option>
|
||||
<option value={TaskTypeEnum.Testing}>Test</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>
|
||||
{Object.values(TaskTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getTaskTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -932,10 +882,11 @@ const ProjectTasks: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -949,21 +900,11 @@ const ProjectTasks: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={TaskStatusEnum.NotStarted}>
|
||||
Başlanmadı
|
||||
</option>
|
||||
<option value={TaskStatusEnum.InProgress}>
|
||||
Devam Ediyor
|
||||
</option>
|
||||
<option value={TaskStatusEnum.Completed}>
|
||||
Tamamlandı
|
||||
</option>
|
||||
<option value={TaskStatusEnum.OnHold}>
|
||||
Beklemede
|
||||
</option>
|
||||
<option value={TaskStatusEnum.Cancelled}>
|
||||
İptal Edildi
|
||||
</option>
|
||||
{Object.values(TaskStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getTaskStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -994,8 +935,7 @@ const ProjectTasks: React.FC = () => {
|
|||
.filter((emp) => emp.isActive)
|
||||
.map((employee) => (
|
||||
<option key={employee.id} value={employee.id}>
|
||||
{employee.fullName} -{" "}
|
||||
{employee.jobPosition?.name}
|
||||
{employee.fullName} - {employee.jobPosition?.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
|
@ -1021,8 +961,8 @@ const ProjectTasks: React.FC = () => {
|
|||
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200">
|
||||
{(() => {
|
||||
const selectedEmployee = mockEmployees.find(
|
||||
(emp) => emp.id === formData.assignedTo
|
||||
);
|
||||
(emp) => emp.id === formData.assignedTo,
|
||||
)
|
||||
return selectedEmployee ? (
|
||||
<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">
|
||||
|
|
@ -1040,7 +980,7 @@ const ProjectTasks: React.FC = () => {
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
) : null
|
||||
})()}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -1126,9 +1066,7 @@ const ProjectTasks: React.FC = () => {
|
|||
<FaFlag className="w-4 h-4" />
|
||||
<span className="text-sm font-medium">Görev Kodu:</span>
|
||||
<span className="font-bold">
|
||||
{isEditModalOpen
|
||||
? editingTask?.taskCode
|
||||
: generateTaskCode()}
|
||||
{isEditModalOpen ? editingTask?.taskCode : generateTaskCode()}
|
||||
</span>
|
||||
</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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{isEditModalOpen ? "Güncelle" : "Oluştur"}
|
||||
{isEditModalOpen ? 'Güncelle' : 'Oluştur'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -1158,8 +1096,7 @@ const ProjectTasks: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectTasks;
|
||||
export default ProjectTasks
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from "../../../types/ps";
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from '../../../types/ps'
|
||||
import {
|
||||
FaPlus,
|
||||
FaEdit,
|
||||
|
|
@ -10,39 +10,40 @@ import {
|
|||
FaUserCog,
|
||||
FaSave,
|
||||
FaTimesCircle,
|
||||
} from "react-icons/fa";
|
||||
import { mockEmployees } from "../../../mocks/mockEmployees";
|
||||
import { mockProjects } from "../../../mocks/mockProjects";
|
||||
import { mockProjectPhases } from "../../../mocks/mockProjectPhases";
|
||||
import { PriorityEnum } from "../../../types/common";
|
||||
} from 'react-icons/fa'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { mockProjects } from '../../../mocks/mockProjects'
|
||||
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||
import { PriorityEnum } from '../../../types/common'
|
||||
import { getPriorityText, getTaskStatusText, getTaskTypeText } from '@/utils/erp'
|
||||
|
||||
export interface TaskFormData {
|
||||
name: string;
|
||||
description: string;
|
||||
projectId: string;
|
||||
phaseId: string;
|
||||
taskType: TaskTypeEnum;
|
||||
status: TaskStatusEnum;
|
||||
priority: PriorityEnum;
|
||||
assignedTo: string;
|
||||
assigneeEmail: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
estimatedHours: number;
|
||||
progress: number;
|
||||
name: string
|
||||
description: string
|
||||
projectId: string
|
||||
phaseId: string
|
||||
taskType: TaskTypeEnum
|
||||
status: TaskStatusEnum
|
||||
priority: PriorityEnum
|
||||
assignedTo: string
|
||||
assigneeEmail: string
|
||||
startDate: string
|
||||
endDate: string
|
||||
estimatedHours: number
|
||||
progress: number
|
||||
}
|
||||
|
||||
interface TaskEditModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
task?: PsProjectTask | null;
|
||||
onSubmit: (taskData: TaskFormData) => void;
|
||||
mode: "create" | "edit";
|
||||
defaultProjectId?: string;
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
task?: PsProjectTask | null
|
||||
onSubmit: (taskData: TaskFormData) => void
|
||||
mode: 'create' | 'edit'
|
||||
defaultProjectId?: string
|
||||
}
|
||||
|
||||
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> = ({
|
||||
isOpen,
|
||||
|
|
@ -53,91 +54,89 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
defaultProjectId,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState<TaskFormData>({
|
||||
name: "",
|
||||
description: "",
|
||||
projectId: "",
|
||||
phaseId: "",
|
||||
name: '',
|
||||
description: '',
|
||||
projectId: '',
|
||||
phaseId: '',
|
||||
taskType: TaskTypeEnum.Development,
|
||||
status: TaskStatusEnum.NotStarted,
|
||||
priority: PriorityEnum.Normal,
|
||||
assignedTo: "",
|
||||
assigneeEmail: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
assignedTo: '',
|
||||
assigneeEmail: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
estimatedHours: 0,
|
||||
progress: 0,
|
||||
});
|
||||
})
|
||||
|
||||
const generateTaskCode = () => {
|
||||
const taskCount = 1; // Bu gerçek uygulamada dinamik olarak hesaplanmalı
|
||||
return `TSK-${taskCount.toString().padStart(3, "0")}`;
|
||||
};
|
||||
const taskCount = 1 // Bu gerçek uygulamada dinamik olarak hesaplanmalı
|
||||
return `TSK-${taskCount.toString().padStart(3, '0')}`
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (mode === "edit" && task) {
|
||||
if (mode === 'edit' && task) {
|
||||
setFormData({
|
||||
name: task.name,
|
||||
description: task.description || "",
|
||||
description: task.description || '',
|
||||
projectId: task.projectId,
|
||||
phaseId: task.phaseId || "",
|
||||
phaseId: task.phaseId || '',
|
||||
taskType: task.taskType,
|
||||
status: task.status,
|
||||
priority: task.priority,
|
||||
assignedTo: task.assignedTo || "",
|
||||
assigneeEmail: task.assignee?.email || "",
|
||||
startDate: task.startDate.toISOString().split("T")[0],
|
||||
endDate: task.endDate.toISOString().split("T")[0],
|
||||
assignedTo: task.assignedTo || '',
|
||||
assigneeEmail: task.assignee?.email || '',
|
||||
startDate: task.startDate.toISOString().split('T')[0],
|
||||
endDate: task.endDate.toISOString().split('T')[0],
|
||||
estimatedHours: task.estimatedHours,
|
||||
progress: task.progress,
|
||||
});
|
||||
})
|
||||
} else {
|
||||
// Reset form for create mode
|
||||
setFormData({
|
||||
name: "",
|
||||
description: "",
|
||||
projectId: defaultProjectId || "",
|
||||
phaseId: "",
|
||||
name: '',
|
||||
description: '',
|
||||
projectId: defaultProjectId || '',
|
||||
phaseId: '',
|
||||
taskType: TaskTypeEnum.Development,
|
||||
status: TaskStatusEnum.NotStarted,
|
||||
priority: PriorityEnum.Normal,
|
||||
assignedTo: "",
|
||||
assigneeEmail: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
assignedTo: '',
|
||||
assigneeEmail: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
estimatedHours: 0,
|
||||
progress: 0,
|
||||
});
|
||||
})
|
||||
}
|
||||
}, [mode, task, isOpen, defaultProjectId]);
|
||||
}, [mode, task, isOpen, defaultProjectId])
|
||||
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<
|
||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
||||
>
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
const { name, value } = e.target;
|
||||
const { name, value } = e.target
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
}));
|
||||
}))
|
||||
|
||||
// Auto-fill email when employee is selected
|
||||
if (name === "assignedTo") {
|
||||
const selectedEmployee = mockEmployees.find((emp) => emp.id === value);
|
||||
if (name === 'assignedTo') {
|
||||
const selectedEmployee = mockEmployees.find((emp) => emp.id === value)
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
assigneeEmail: selectedEmployee?.email || "",
|
||||
}));
|
||||
assigneeEmail: selectedEmployee?.email || '',
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
onSubmit(formData);
|
||||
onClose();
|
||||
};
|
||||
e.preventDefault()
|
||||
onSubmit(formData)
|
||||
onClose()
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<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 gap-2">
|
||||
<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" />
|
||||
) : (
|
||||
<FaPlus className="w-3.5 h-3.5 text-white" />
|
||||
|
|
@ -154,12 +153,12 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
</div>
|
||||
<div>
|
||||
<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>
|
||||
<p className="text-xs text-gray-600">
|
||||
{mode === "edit"
|
||||
? "Mevcut görev bilgilerini güncelleyin"
|
||||
: "Yeni bir görev tanımlayın"}
|
||||
{mode === 'edit'
|
||||
? 'Mevcut görev bilgilerini güncelleyin'
|
||||
: 'Yeni bir görev tanımlayın'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -217,15 +216,11 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
disabled={!formData.projectId}
|
||||
>
|
||||
<option value="">
|
||||
{formData.projectId
|
||||
? "Aşama seçin..."
|
||||
: "Önce proje seçin"}
|
||||
{formData.projectId ? 'Aşama seçin...' : 'Önce proje seçin'}
|
||||
</option>
|
||||
{formData.projectId &&
|
||||
mockProjectPhases
|
||||
.filter(
|
||||
(phase) => phase.projectId === formData.projectId
|
||||
)
|
||||
.filter((phase) => phase.projectId === formData.projectId)
|
||||
.map((phase) => (
|
||||
<option key={phase.id} value={phase.id}>
|
||||
{phase.code} - {phase.name}
|
||||
|
|
@ -250,9 +245,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Açıklama
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama</label>
|
||||
<textarea
|
||||
name="description"
|
||||
value={formData.description}
|
||||
|
|
@ -273,59 +266,43 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
onChange={handleInputChange}
|
||||
className={inputClasses}
|
||||
>
|
||||
<option value={TaskTypeEnum.Development}>
|
||||
Geliştirme
|
||||
</option>
|
||||
<option value={TaskTypeEnum.Testing}>Test</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>
|
||||
{Object.values(TaskTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getTaskTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Öncelik
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Öncelik</label>
|
||||
<select
|
||||
name="priority"
|
||||
value={formData.priority}
|
||||
onChange={handleInputChange}
|
||||
className={inputClasses}
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Durum
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||
<select
|
||||
name="status"
|
||||
value={formData.status}
|
||||
onChange={handleInputChange}
|
||||
className={inputClasses}
|
||||
>
|
||||
<option value={TaskStatusEnum.NotStarted}>
|
||||
Başlanmadı
|
||||
</option>
|
||||
<option value={TaskStatusEnum.InProgress}>
|
||||
Devam Ediyor
|
||||
</option>
|
||||
<option value={TaskStatusEnum.Completed}>
|
||||
Tamamlandı
|
||||
</option>
|
||||
<option value={TaskStatusEnum.OnHold}>Beklemede</option>
|
||||
<option value={TaskStatusEnum.Cancelled}>
|
||||
İptal Edildi
|
||||
</option>
|
||||
{Object.values(TaskStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getTaskStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -363,9 +340,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
E-posta
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
|
||||
<input
|
||||
type="email"
|
||||
name="assigneeEmail"
|
||||
|
|
@ -381,8 +356,8 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
{formData.assignedTo &&
|
||||
(() => {
|
||||
const selectedEmployee = mockEmployees.find(
|
||||
(emp) => emp.id === formData.assignedTo
|
||||
);
|
||||
(emp) => emp.id === formData.assignedTo,
|
||||
)
|
||||
return selectedEmployee ? (
|
||||
<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">
|
||||
|
|
@ -400,7 +375,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
) : null
|
||||
})()}
|
||||
|
||||
<div className="grid grid-cols-2 gap-2.5">
|
||||
|
|
@ -448,7 +423,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
/>
|
||||
</div>
|
||||
|
||||
{mode === "edit" && (
|
||||
{mode === 'edit' && (
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
İlerleme (%)
|
||||
|
|
@ -484,7 +459,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
|||
<FaFlag className="w-4 h-4" />
|
||||
<span className="text-sm font-medium">Görev Kodu:</span>
|
||||
<span className="font-bold">
|
||||
{mode === "edit" ? task?.taskCode : generateTaskCode()}
|
||||
{mode === 'edit' ? task?.taskCode : generateTaskCode()}
|
||||
</span>
|
||||
</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"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{mode === "edit" ? "Güncelle" : "Oluştur"}
|
||||
{mode === 'edit' ? 'Güncelle' : 'Oluştur'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default TaskEditModal;
|
||||
export default TaskEditModal
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from '../../../types/mm'
|
||||
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
||||
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||
import { getApprovalLevelText, getRequestTypeText } from '@/utils/erp'
|
||||
|
||||
interface ApprovalWorkflowModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -195,10 +196,11 @@ const ApprovalWorkflowModal: React.FC<ApprovalWorkflowModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={RequestTypeEnum.Material}>Malzeme</option>
|
||||
<option value={RequestTypeEnum.Service}>Hizmet</option>
|
||||
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option>
|
||||
<option value={RequestTypeEnum.Maintenance}>Bakım</option>
|
||||
{Object.values(RequestTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getRequestTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -276,14 +278,11 @@ const ApprovalWorkflowModal: React.FC<ApprovalWorkflowModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={ApprovalLevelEnum.Supervisor}>Süpervizör</option>
|
||||
<option value={ApprovalLevelEnum.Manager}>Müdür</option>
|
||||
<option value={ApprovalLevelEnum.Director}>Direktör</option>
|
||||
<option value={ApprovalLevelEnum.GeneralManager}>Genel Müdür</option>
|
||||
<option value={ApprovalLevelEnum.FinanceManager}>
|
||||
Mali İşler Müdürü
|
||||
</option>
|
||||
<option value={ApprovalLevelEnum.TechnicalManager}>Teknik Müdür</option>
|
||||
{Object.values(ApprovalLevelEnum).map((lvl) => (
|
||||
<option key={lvl} value={lvl}>
|
||||
{getApprovalLevelText(lvl)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={DeliveryStatusEnum.Preparing}>Hazırlanıyor</option>
|
||||
<option value={DeliveryStatusEnum.Shipped}>Kargoya Verildi</option>
|
||||
<option value={DeliveryStatusEnum.InTransit}>Yolda</option>
|
||||
<option value={DeliveryStatusEnum.OutForDelivery}>Dağıtımda</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>
|
||||
{Object.values(DeliveryStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getDeliveryStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import {
|
|||
QualityStatusEnum,
|
||||
MmGoodsReceiptItem,
|
||||
} from '../../../types/mm'
|
||||
import { mock } from 'node:test'
|
||||
import { mockWarehouses } from '@/mocks/mockWarehouses'
|
||||
import { getQualityStatusText, getReceiptStatusText } from '@/utils/erp'
|
||||
|
||||
interface DeliveryTrackingModalProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -226,10 +229,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
|
|||
required
|
||||
>
|
||||
<option value="">Depo Seçiniz</option>
|
||||
<option value="WH001">Ana Depo</option>
|
||||
<option value="WH002">Hammadde Deposu</option>
|
||||
<option value="WH003">Mamul Deposu</option>
|
||||
<option value="WH004">Yedek Parça Deposu</option>
|
||||
{mockWarehouses.map((wh) => (
|
||||
<option key={wh.id} value={wh.id}>
|
||||
{wh.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -242,10 +246,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={ReceiptStatusEnum.Pending}>Beklemede</option>
|
||||
<option value={ReceiptStatusEnum.InProgress}>İşlemde</option>
|
||||
<option value={ReceiptStatusEnum.Completed}>Tamamlandı</option>
|
||||
<option value={ReceiptStatusEnum.OnHold}>Bekletildi</option>
|
||||
{Object.values(ReceiptStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getReceiptStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -402,10 +407,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value={QualityStatusEnum.Pending}>Beklemede</option>
|
||||
<option value={QualityStatusEnum.Approved}>Kabul</option>
|
||||
<option value={QualityStatusEnum.Rejected}>Red</option>
|
||||
<option value={QualityStatusEnum.Conditional}>Koşullu</option>
|
||||
{Object.values(QualityStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getQualityStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { MaterialTypeEnum, MmMaterialType } from '@/types/mm'
|
||||
import { getMaterialTypeText } from '@/utils/erp'
|
||||
import { useState } from 'react'
|
||||
|
||||
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"
|
||||
required
|
||||
>
|
||||
<option value={MaterialTypeEnum.RawMaterial}>Hammadde</option>
|
||||
<option value={MaterialTypeEnum.SemiFinished}>Yarı Mamul</option>
|
||||
<option value={MaterialTypeEnum.Finished}>Mamul</option>
|
||||
<option value={MaterialTypeEnum.Consumable}>Sarf Malzemesi</option>
|
||||
<option value={MaterialTypeEnum.Service}>Hizmet</option>
|
||||
<option value={MaterialTypeEnum.Spare}>Yedek Parça</option>
|
||||
{Object.values(MaterialTypeEnum).map((value) => (
|
||||
<option key={value} value={value}>
|
||||
{getMaterialTypeText(value)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react'
|
|||
import { FaPlus, FaEdit, FaTrash, FaSearch, FaTh, FaList } from 'react-icons/fa'
|
||||
import { MmMaterialType, MaterialTypeEnum } from '../../../types/mm'
|
||||
import { mockMaterialTypes } from '../../../mocks/mockMaterialTypes'
|
||||
import { getMaterialTypeDisplay } from '../../../utils/erp'
|
||||
import { getMaterialTypeText } from '../../../utils/erp'
|
||||
import { Container } from '@/components/shared'
|
||||
import MaterialTypeModal from './MaterialTypeModal'
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ const MaterialTypes: React.FC = () => {
|
|||
<tr key={type.id} className="hover:bg-gray-50 text-xs">
|
||||
<td className="px-3 py-1.5 whitespace-nowrap">
|
||||
<span className="text-sm font-mono font-medium text-gray-900">
|
||||
{getMaterialTypeDisplay(type.code)}
|
||||
{getMaterialTypeText(type.code)}
|
||||
</span>
|
||||
</td>
|
||||
<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-1">
|
||||
<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>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tüm Durumlar</option>
|
||||
<option value={OrderStatusEnum.Draft}>Taslak</option>
|
||||
<option value={OrderStatusEnum.Pending}>Beklemede</option>
|
||||
<option value={OrderStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={OrderStatusEnum.Sent}>Gönderildi</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>
|
||||
{Object.values(OrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -559,14 +555,11 @@ const OrderManagement: React.FC = () => {
|
|||
defaultValue=""
|
||||
>
|
||||
<option value="">Durum Seçiniz</option>
|
||||
<option value={OrderStatusEnum.Pending}>Beklemede</option>
|
||||
<option value={OrderStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={OrderStatusEnum.Sent}>Gönderildi</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>
|
||||
{Object.values(OrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import { mockPurchaseOrders } from '../../../mocks/mockPurchaseOrders'
|
|||
import { Address, PaymentTerms } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { getOrderStatusText, getPaymentTermsText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
const OrderManagementForm: React.FC = () => {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
|
|
@ -318,14 +320,11 @@ const OrderManagementForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={PaymentTerms.Net15}>15 Gün Vadeli</option>
|
||||
<option value={PaymentTerms.Net30}>30 Gün Vadeli</option>
|
||||
<option value={PaymentTerms.Net45}>45 Gün Vadeli</option>
|
||||
<option value={PaymentTerms.Net60}>60 Gün Vadeli</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>
|
||||
{Object.values(PaymentTerms).map((term) => (
|
||||
<option key={term} value={term}>
|
||||
{getPaymentTermsText(term)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -338,9 +337,11 @@ const OrderManagementForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -654,14 +655,11 @@ const OrderManagementForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={OrderStatusEnum.Draft}>Taslak</option>
|
||||
<option value={OrderStatusEnum.Sent}>Gönderildi</option>
|
||||
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option>
|
||||
<option value={OrderStatusEnum.PartiallyReceived}>Kısmi Teslim</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>
|
||||
{Object.values(OrderStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getOrderStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import { mockPurchaseRequests } from '../../../mocks/mockPurchaseRequests'
|
|||
import { PriorityEnum } from '../../../types/common'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { getPriorityText, getRequestStatusText, getRequestTypeText } from '@/utils/erp'
|
||||
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||
|
||||
const PurchaseRequestForm: React.FC = () => {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
|
|
@ -198,10 +200,11 @@ const PurchaseRequestForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={RequestTypeEnum.Material}>Malzeme</option>
|
||||
<option value={RequestTypeEnum.Service}>Hizmet</option>
|
||||
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option>
|
||||
<option value={RequestTypeEnum.Maintenance}>Bakım</option>
|
||||
{Object.values(RequestTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getRequestTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -294,10 +297,11 @@ const PurchaseRequestForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -310,9 +314,11 @@ const PurchaseRequestForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="TRY">TRY</option>
|
||||
<option value="USD">USD</option>
|
||||
<option value="EUR">EUR</option>
|
||||
{mockCurrencies.map((currency) => (
|
||||
<option key={currency.value} value={currency.value}>
|
||||
{currency.value} - {currency.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -500,12 +506,11 @@ const PurchaseRequestForm: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value={RequestStatusEnum.Draft}>Taslak</option>
|
||||
<option value={RequestStatusEnum.Submitted}>Gönderildi</option>
|
||||
<option value={RequestStatusEnum.InReview}>İncelemede</option>
|
||||
<option value={RequestStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={RequestStatusEnum.Rejected}>Reddedildi</option>
|
||||
<option value={RequestStatusEnum.Cancelled}>İptal Edildi</option>
|
||||
{Object.values(RequestStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getRequestStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -96,23 +96,24 @@ const PurchaseRequests: React.FC = () => {
|
|||
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"
|
||||
>
|
||||
<option value="ALL">Tüm Durumlar</option>
|
||||
<option value={RequestStatusEnum.Draft}>Taslak</option>
|
||||
<option value={RequestStatusEnum.Submitted}>Gönderildi</option>
|
||||
<option value={RequestStatusEnum.InReview}>İnceleniyor</option>
|
||||
<option value={RequestStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={RequestStatusEnum.Rejected}>Reddedildi</option>
|
||||
<option value="All">Tüm Durumlar</option>
|
||||
{Object.values(RequestStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getRequestStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<select
|
||||
value={filterType}
|
||||
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"
|
||||
>
|
||||
<option value="ALL">Tüm Türler</option>
|
||||
<option value={RequestTypeEnum.Material}>Malzeme</option>
|
||||
<option value={RequestTypeEnum.Service}>Hizmet</option>
|
||||
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option>
|
||||
<option value={RequestTypeEnum.Maintenance}>Bakım</option>
|
||||
<option value="All">Tüm Türler</option>
|
||||
{Object.values(RequestTypeEnum).map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{getRequestTypeText(type)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={RequisitionStatusEnum.Draft}>Taslak</option>
|
||||
<option value={RequisitionStatusEnum.Submitted}>Gönderildi</option>
|
||||
<option value={RequisitionStatusEnum.InApproval}>Onayda</option>
|
||||
<option value={RequisitionStatusEnum.Approved}>Onaylandı</option>
|
||||
<option value={RequisitionStatusEnum.Rejected}>Reddedildi</option>
|
||||
{Object.values(RequisitionStatusEnum).map((status) => (
|
||||
<option key={status} value={status}>
|
||||
{getRequisitionStatusText(status)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</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"
|
||||
>
|
||||
<option value="all">Tümü</option>
|
||||
<option value={PriorityEnum.Low}>Düşük</option>
|
||||
<option value={PriorityEnum.Normal}>Normal</option>
|
||||
<option value={PriorityEnum.High}>Yüksek</option>
|
||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
||||
{Object.values(PriorityEnum).map((priority) => (
|
||||
<option key={priority} value={priority}>
|
||||
{getPriorityText(priority)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue