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"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "/index.html",
|
"url": "/index.html",
|
||||||
"revision": "0.bkv2hic80pg"
|
"revision": "0.h99odp2o5hg"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), {
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ const EntityManager: React.FC = () => {
|
||||||
</p>
|
</p>
|
||||||
{!searchTerm && filterActive === 'all' && (
|
{!searchTerm && filterActive === 'all' && (
|
||||||
<Link
|
<Link
|
||||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
to={ROUTES_ENUM.protected.saas.developerKit.entitiesNew}
|
||||||
className="inline-flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors shadow-sm hover:shadow-md"
|
className="inline-flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors shadow-sm hover:shadow-md"
|
||||||
>
|
>
|
||||||
<FaPlus className="w-4 h-4" />
|
<FaPlus className="w-4 h-4" />
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,51 @@
|
||||||
import { BankAccountTypeEnum } from "../types/fi";
|
import { BankAccountTypeEnum } from '../types/fi'
|
||||||
import { BusinessParty, BusinessPartyStatusEnum, PartyType, PaymentTerms } from "../types/common";
|
import { BusinessParty, BusinessPartyStatusEnum, PartyType, PaymentTerms } from '../types/common'
|
||||||
import {
|
import { CustomerSegmentEnum, CustomerTypeEnum } from '../types/crm'
|
||||||
CustomerSegmentEnum,
|
import { SupplierTypeEnum, SupplierCardTypeEnum } from '../types/mm'
|
||||||
CustomerTypeEnum,
|
|
||||||
} from "../types/crm";
|
|
||||||
import { SupplierTypeEnum, SupplierCardTypeEnum } from "../types/mm";
|
|
||||||
|
|
||||||
export const mockBusinessParties: BusinessParty[] = [
|
export const mockBusinessParties: BusinessParty[] = [
|
||||||
{
|
{
|
||||||
id: "1",
|
id: '1',
|
||||||
code: "SUP001",
|
code: 'SUP001',
|
||||||
supplierType: SupplierTypeEnum.Material,
|
supplierType: SupplierTypeEnum.Manufacturer,
|
||||||
name: "ABC Malzeme Ltd.",
|
name: 'ABC Malzeme Ltd.',
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
id: "2",
|
id: '2',
|
||||||
firstName: "Fatma",
|
firstName: 'Fatma',
|
||||||
lastName: "Demir",
|
lastName: 'Demir',
|
||||||
fullName: "Fatma Demir",
|
fullName: 'Fatma Demir',
|
||||||
title: "Genel Müdür",
|
title: 'Genel Müdür',
|
||||||
department: "Yönetim",
|
department: 'Yönetim',
|
||||||
email: "fatma.demir@uretim.com",
|
email: 'fatma.demir@uretim.com',
|
||||||
phone: "+90 312 555 0202",
|
phone: '+90 312 555 0202',
|
||||||
mobile: "+90 532 555 0202",
|
mobile: '+90 532 555 0202',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
},
|
},
|
||||||
email: "aliveli@gmail.com",
|
email: 'aliveli@gmail.com',
|
||||||
phone: "+90 212 555 1234",
|
phone: '+90 212 555 1234',
|
||||||
address: {
|
address: {
|
||||||
street: "İstiklal Cad. No:10",
|
street: 'İstiklal Cad. No:10',
|
||||||
city: "İstanbul",
|
city: 'İstanbul',
|
||||||
state: "İstanbul",
|
state: 'İstanbul',
|
||||||
postalCode: "34430",
|
postalCode: '34430',
|
||||||
country: "Türkiye",
|
country: 'Türkiye',
|
||||||
},
|
},
|
||||||
taxNumber: "1234567890",
|
taxNumber: '1234567890',
|
||||||
paymentTerms: PaymentTerms.Net30,
|
paymentTerms: PaymentTerms.Net30,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
cardNumber: "SC-2024-001",
|
cardNumber: 'SC-2024-001',
|
||||||
cardType: SupplierCardTypeEnum.Standard,
|
cardType: SupplierCardTypeEnum.Standard,
|
||||||
validFrom: new Date("2024-01-01"),
|
validFrom: new Date('2024-01-01'),
|
||||||
validTo: new Date("2024-12-31"),
|
validTo: new Date('2024-12-31'),
|
||||||
creditLimit: 500000,
|
creditLimit: 500000,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
currentBalance: 120000,
|
currentBalance: 120000,
|
||||||
discountRate: 5,
|
discountRate: 5,
|
||||||
specialConditions: ["Toplu sipariş indirimi", "Öncelikli teslimat"],
|
specialConditions: ['Toplu sipariş indirimi', 'Öncelikli teslimat'],
|
||||||
lastOrderDate: new Date("2024-08-15"),
|
lastOrderDate: new Date('2024-08-15'),
|
||||||
performanceMetrics: {
|
performanceMetrics: {
|
||||||
deliveryPerformance: 95,
|
deliveryPerformance: 95,
|
||||||
qualityRating: 90,
|
qualityRating: 90,
|
||||||
|
|
@ -56,21 +53,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
responsiveness: 67,
|
responsiveness: 67,
|
||||||
complianceRating: 88,
|
complianceRating: 88,
|
||||||
overallScore: 100,
|
overallScore: 100,
|
||||||
lastEvaluationDate: new Date("2024-08-01"),
|
lastEvaluationDate: new Date('2024-08-01'),
|
||||||
},
|
},
|
||||||
certifications: ["ISO 9001", "ISO 14001"],
|
certifications: ['ISO 9001', 'ISO 14001'],
|
||||||
bankAccounts: [
|
bankAccounts: [
|
||||||
{
|
{
|
||||||
id: "BA001",
|
id: 'BA001',
|
||||||
bankName: "Garanti BBVA",
|
bankName: 'Garanti BBVA',
|
||||||
accountNumber: "1234567890",
|
accountNumber: '1234567890',
|
||||||
iban: "TR330006100519786457841326",
|
iban: 'TR330006100519786457841326',
|
||||||
swiftCode: "TGBATRIS",
|
swiftCode: 'TGBATRIS',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountType: BankAccountTypeEnum.Current,
|
accountType: BankAccountTypeEnum.Current,
|
||||||
currency: "",
|
currency: '',
|
||||||
balance: 0,
|
balance: 0,
|
||||||
overdraftLimit: 0,
|
overdraftLimit: 0,
|
||||||
dailyTransferLimit: 0,
|
dailyTransferLimit: 0,
|
||||||
|
|
@ -81,14 +78,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
],
|
],
|
||||||
contacts: [
|
contacts: [
|
||||||
{
|
{
|
||||||
id: "C001",
|
id: 'C001',
|
||||||
firstName: "Ali",
|
firstName: 'Ali',
|
||||||
lastName: "Veli",
|
lastName: 'Veli',
|
||||||
fullName: "Ali Veli",
|
fullName: 'Ali Veli',
|
||||||
title: "Satınalma Müdürü",
|
title: 'Satınalma Müdürü',
|
||||||
email: "aliveli@gmail.com",
|
email: 'aliveli@gmail.com',
|
||||||
phone: "+90 212 555 1234",
|
phone: '+90 212 555 1234',
|
||||||
department: "Satınalma",
|
department: 'Satınalma',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -100,47 +97,47 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
partyType: PartyType.Supplier,
|
partyType: PartyType.Supplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: '2',
|
||||||
code: "SUP002",
|
code: 'SUP002',
|
||||||
supplierType: SupplierTypeEnum.Service,
|
supplierType: SupplierTypeEnum.ServiceProvider,
|
||||||
name: "XYZ Teknoloji A.Ş.",
|
name: 'XYZ Teknoloji A.Ş.',
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
id: "2",
|
id: '2',
|
||||||
firstName: "Fatma",
|
firstName: 'Fatma',
|
||||||
lastName: "Demir",
|
lastName: 'Demir',
|
||||||
fullName: "Fatma Demir",
|
fullName: 'Fatma Demir',
|
||||||
title: "Genel Müdür",
|
title: 'Genel Müdür',
|
||||||
department: "Yönetim",
|
department: 'Yönetim',
|
||||||
email: "fatma.demir@uretim.com",
|
email: 'fatma.demir@uretim.com',
|
||||||
phone: "+90 312 555 0202",
|
phone: '+90 312 555 0202',
|
||||||
mobile: "+90 532 555 0202",
|
mobile: '+90 532 555 0202',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
},
|
},
|
||||||
email: "aysedemir@gmail.com",
|
email: 'aysedemir@gmail.com',
|
||||||
phone: "+90 216 555 5678",
|
phone: '+90 216 555 5678',
|
||||||
address: {
|
address: {
|
||||||
street: "Barbaros Bulv. No:20",
|
street: 'Barbaros Bulv. No:20',
|
||||||
city: "İstanbul",
|
city: 'İstanbul',
|
||||||
state: "İstanbul",
|
state: 'İstanbul',
|
||||||
postalCode: "34746",
|
postalCode: '34746',
|
||||||
country: "Türkiye",
|
country: 'Türkiye',
|
||||||
},
|
},
|
||||||
taxNumber: "0987654321",
|
taxNumber: '0987654321',
|
||||||
paymentTerms: PaymentTerms.Net15,
|
paymentTerms: PaymentTerms.Net15,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
cardNumber: "SC-2024-002",
|
cardNumber: 'SC-2024-002',
|
||||||
cardType: SupplierCardTypeEnum.Premium,
|
cardType: SupplierCardTypeEnum.Premium,
|
||||||
validFrom: new Date("2024-02-01"),
|
validFrom: new Date('2024-02-01'),
|
||||||
validTo: new Date("2024-12-31"),
|
validTo: new Date('2024-12-31'),
|
||||||
creditLimit: 250000,
|
creditLimit: 250000,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
currentBalance: 75000,
|
currentBalance: 75000,
|
||||||
discountRate: 3,
|
discountRate: 3,
|
||||||
specialConditions: ["Hızlı teslimat", "Kalite garantisi"],
|
specialConditions: ['Hızlı teslimat', 'Kalite garantisi'],
|
||||||
lastOrderDate: new Date("2024-08-20"),
|
lastOrderDate: new Date('2024-08-20'),
|
||||||
performanceMetrics: {
|
performanceMetrics: {
|
||||||
deliveryPerformance: 88,
|
deliveryPerformance: 88,
|
||||||
qualityRating: 90,
|
qualityRating: 90,
|
||||||
|
|
@ -148,21 +145,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
responsiveness: 87,
|
responsiveness: 87,
|
||||||
complianceRating: 91,
|
complianceRating: 91,
|
||||||
overallScore: 88,
|
overallScore: 88,
|
||||||
lastEvaluationDate: new Date("2024-08-01"),
|
lastEvaluationDate: new Date('2024-08-01'),
|
||||||
},
|
},
|
||||||
certifications: ["ISO 9001"],
|
certifications: ['ISO 9001'],
|
||||||
bankAccounts: [
|
bankAccounts: [
|
||||||
{
|
{
|
||||||
id: "BA002",
|
id: 'BA002',
|
||||||
bankName: "İş Bankası",
|
bankName: 'İş Bankası',
|
||||||
accountNumber: "0987654321",
|
accountNumber: '0987654321',
|
||||||
iban: "TR440006200519786457841327",
|
iban: 'TR440006200519786457841327',
|
||||||
swiftCode: "ISBKTRIS",
|
swiftCode: 'ISBKTRIS',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountType: BankAccountTypeEnum.Current,
|
accountType: BankAccountTypeEnum.Current,
|
||||||
currency: "",
|
currency: '',
|
||||||
balance: 0,
|
balance: 0,
|
||||||
overdraftLimit: 0,
|
overdraftLimit: 0,
|
||||||
dailyTransferLimit: 0,
|
dailyTransferLimit: 0,
|
||||||
|
|
@ -173,14 +170,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
],
|
],
|
||||||
contacts: [
|
contacts: [
|
||||||
{
|
{
|
||||||
id: "C002",
|
id: 'C002',
|
||||||
firstName: "Ayşe",
|
firstName: 'Ayşe',
|
||||||
lastName: "Demir",
|
lastName: 'Demir',
|
||||||
fullName: "Ayşe Demir",
|
fullName: 'Ayşe Demir',
|
||||||
title: "Satış Müdürü",
|
title: 'Satış Müdürü',
|
||||||
email: "aysedemir@gmail.com",
|
email: 'aysedemir@gmail.com',
|
||||||
phone: "+90 216 555 5678",
|
phone: '+90 216 555 5678',
|
||||||
department: "Satış",
|
department: 'Satış',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -192,47 +189,47 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
partyType: PartyType.Supplier,
|
partyType: PartyType.Supplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "3",
|
id: '3',
|
||||||
code: "SUP003",
|
code: 'SUP003',
|
||||||
supplierType: SupplierTypeEnum.Both,
|
supplierType: SupplierTypeEnum.Manufacturer,
|
||||||
name: "LMN Endüstri A.Ş.",
|
name: 'LMN Endüstri A.Ş.',
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
id: "2",
|
id: '2',
|
||||||
firstName: "Fatma",
|
firstName: 'Fatma',
|
||||||
lastName: "Demir",
|
lastName: 'Demir',
|
||||||
fullName: "Fatma Demir",
|
fullName: 'Fatma Demir',
|
||||||
title: "Genel Müdür",
|
title: 'Genel Müdür',
|
||||||
department: "Yönetim",
|
department: 'Yönetim',
|
||||||
email: "fatma.demir@uretim.com",
|
email: 'fatma.demir@uretim.com',
|
||||||
phone: "+90 312 555 0202",
|
phone: '+90 312 555 0202',
|
||||||
mobile: "+90 532 555 0202",
|
mobile: '+90 532 555 0202',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
},
|
},
|
||||||
email: "mehmetyilmaz@gmail.com",
|
email: 'mehmetyilmaz@gmail.com',
|
||||||
phone: "+90 232 555 7890",
|
phone: '+90 232 555 7890',
|
||||||
address: {
|
address: {
|
||||||
street: "Atatürk Cad. No:5",
|
street: 'Atatürk Cad. No:5',
|
||||||
city: "İzmir",
|
city: 'İzmir',
|
||||||
state: "İzmir",
|
state: 'İzmir',
|
||||||
postalCode: "35210",
|
postalCode: '35210',
|
||||||
country: "Türkiye",
|
country: 'Türkiye',
|
||||||
},
|
},
|
||||||
taxNumber: "1122334455",
|
taxNumber: '1122334455',
|
||||||
paymentTerms: PaymentTerms.Net45,
|
paymentTerms: PaymentTerms.Net45,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
cardNumber: "SC-2024-003",
|
cardNumber: 'SC-2024-003',
|
||||||
cardType: SupplierCardTypeEnum.Preferred,
|
cardType: SupplierCardTypeEnum.Preferred,
|
||||||
validFrom: new Date("2024-03-01"),
|
validFrom: new Date('2024-03-01'),
|
||||||
validTo: new Date("2024-12-31"),
|
validTo: new Date('2024-12-31'),
|
||||||
creditLimit: 150000,
|
creditLimit: 150000,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
currentBalance: 45000,
|
currentBalance: 45000,
|
||||||
discountRate: 2,
|
discountRate: 2,
|
||||||
specialConditions: ["Toplu sipariş indirimi"],
|
specialConditions: ['Toplu sipariş indirimi'],
|
||||||
lastOrderDate: new Date("2024-08-18"),
|
lastOrderDate: new Date('2024-08-18'),
|
||||||
performanceMetrics: {
|
performanceMetrics: {
|
||||||
deliveryPerformance: 82,
|
deliveryPerformance: 82,
|
||||||
qualityRating: 85,
|
qualityRating: 85,
|
||||||
|
|
@ -240,21 +237,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
responsiveness: 80,
|
responsiveness: 80,
|
||||||
complianceRating: 88,
|
complianceRating: 88,
|
||||||
overallScore: 85,
|
overallScore: 85,
|
||||||
lastEvaluationDate: new Date("2024-07-15"),
|
lastEvaluationDate: new Date('2024-07-15'),
|
||||||
},
|
},
|
||||||
certifications: ["ISO 9001", "OHSAS 18001"],
|
certifications: ['ISO 9001', 'OHSAS 18001'],
|
||||||
bankAccounts: [
|
bankAccounts: [
|
||||||
{
|
{
|
||||||
id: "BA003",
|
id: 'BA003',
|
||||||
bankName: "Yapı Kredi",
|
bankName: 'Yapı Kredi',
|
||||||
accountNumber: "1122334455",
|
accountNumber: '1122334455',
|
||||||
iban: "TR550006300519786457841328",
|
iban: 'TR550006300519786457841328',
|
||||||
swiftCode: "YAPITRIS",
|
swiftCode: 'YAPITRIS',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountType: BankAccountTypeEnum.Current,
|
accountType: BankAccountTypeEnum.Current,
|
||||||
currency: "",
|
currency: '',
|
||||||
balance: 0,
|
balance: 0,
|
||||||
overdraftLimit: 0,
|
overdraftLimit: 0,
|
||||||
dailyTransferLimit: 0,
|
dailyTransferLimit: 0,
|
||||||
|
|
@ -265,14 +262,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
],
|
],
|
||||||
contacts: [
|
contacts: [
|
||||||
{
|
{
|
||||||
id: "C003",
|
id: 'C003',
|
||||||
firstName: "Mehmet",
|
firstName: 'Mehmet',
|
||||||
lastName: "Yılmaz",
|
lastName: 'Yılmaz',
|
||||||
fullName: "Mehmet Yılmaz",
|
fullName: 'Mehmet Yılmaz',
|
||||||
title: "Genel Müdür",
|
title: 'Genel Müdür',
|
||||||
email: "mehmetyilmaz@gmail.com",
|
email: 'mehmetyilmaz@gmail.com',
|
||||||
phone: "+90 232 555 7890",
|
phone: '+90 232 555 7890',
|
||||||
department: "Yönetim",
|
department: 'Yönetim',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -284,47 +281,47 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
partyType: PartyType.Supplier,
|
partyType: PartyType.Supplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4",
|
id: '4',
|
||||||
code: "SUP004",
|
code: 'SUP004',
|
||||||
supplierType: SupplierTypeEnum.Material,
|
supplierType: SupplierTypeEnum.Distributor,
|
||||||
name: "OPQ Ticaret Ltd.",
|
name: 'OPQ Ticaret Ltd.',
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
id: "2",
|
id: '2',
|
||||||
firstName: "Fatma",
|
firstName: 'Fatma',
|
||||||
lastName: "Demir",
|
lastName: 'Demir',
|
||||||
fullName: "Fatma Demir",
|
fullName: 'Fatma Demir',
|
||||||
title: "Genel Müdür",
|
title: 'Genel Müdür',
|
||||||
department: "Yönetim",
|
department: 'Yönetim',
|
||||||
email: "fatma.demir@uretim.com",
|
email: 'fatma.demir@uretim.com',
|
||||||
phone: "+90 312 555 0202",
|
phone: '+90 312 555 0202',
|
||||||
mobile: "+90 532 555 0202",
|
mobile: '+90 532 555 0202',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
},
|
},
|
||||||
email: "fatmacelik@gmail.com",
|
email: 'fatmacelik@gmail.com',
|
||||||
phone: "+90 312 555 3456",
|
phone: '+90 312 555 3456',
|
||||||
address: {
|
address: {
|
||||||
street: "Kızılay Meydanı No:15",
|
street: 'Kızılay Meydanı No:15',
|
||||||
city: "Ankara",
|
city: 'Ankara',
|
||||||
state: "Ankara",
|
state: 'Ankara',
|
||||||
postalCode: "06690",
|
postalCode: '06690',
|
||||||
country: "Türkiye",
|
country: 'Türkiye',
|
||||||
},
|
},
|
||||||
taxNumber: "6677889900",
|
taxNumber: '6677889900',
|
||||||
paymentTerms: PaymentTerms.Net30,
|
paymentTerms: PaymentTerms.Net30,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
cardNumber: "SC-2024-004",
|
cardNumber: 'SC-2024-004',
|
||||||
cardType: SupplierCardTypeEnum.Standard,
|
cardType: SupplierCardTypeEnum.Standard,
|
||||||
validFrom: new Date("2024-04-01"),
|
validFrom: new Date('2024-04-01'),
|
||||||
validTo: new Date("2024-12-31"),
|
validTo: new Date('2024-12-31'),
|
||||||
creditLimit: 100000,
|
creditLimit: 100000,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
currentBalance: 30000,
|
currentBalance: 30000,
|
||||||
discountRate: 4,
|
discountRate: 4,
|
||||||
specialConditions: ["Öncelikli sipariş", "Hızlı teslimat"],
|
specialConditions: ['Öncelikli sipariş', 'Hızlı teslimat'],
|
||||||
lastOrderDate: new Date("2024-06-30"),
|
lastOrderDate: new Date('2024-06-30'),
|
||||||
performanceMetrics: {
|
performanceMetrics: {
|
||||||
deliveryPerformance: 75,
|
deliveryPerformance: 75,
|
||||||
qualityRating: 78,
|
qualityRating: 78,
|
||||||
|
|
@ -332,21 +329,21 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
responsiveness: 76,
|
responsiveness: 76,
|
||||||
complianceRating: 80,
|
complianceRating: 80,
|
||||||
overallScore: 78,
|
overallScore: 78,
|
||||||
lastEvaluationDate: new Date("2024-07-01"),
|
lastEvaluationDate: new Date('2024-07-01'),
|
||||||
},
|
},
|
||||||
certifications: ["ISO 9001"],
|
certifications: ['ISO 9001'],
|
||||||
bankAccounts: [
|
bankAccounts: [
|
||||||
{
|
{
|
||||||
id: "BA004",
|
id: 'BA004',
|
||||||
bankName: "Halkbank",
|
bankName: 'Halkbank',
|
||||||
accountNumber: "6677889900",
|
accountNumber: '6677889900',
|
||||||
iban: "TR660006400519786457841329",
|
iban: 'TR660006400519786457841329',
|
||||||
swiftCode: "HALKTRIS",
|
swiftCode: 'HALKTRIS',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountType: BankAccountTypeEnum.Current,
|
accountType: BankAccountTypeEnum.Current,
|
||||||
currency: "",
|
currency: '',
|
||||||
balance: 0,
|
balance: 0,
|
||||||
overdraftLimit: 0,
|
overdraftLimit: 0,
|
||||||
dailyTransferLimit: 0,
|
dailyTransferLimit: 0,
|
||||||
|
|
@ -357,14 +354,14 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
],
|
],
|
||||||
contacts: [
|
contacts: [
|
||||||
{
|
{
|
||||||
id: "C004",
|
id: 'C004',
|
||||||
firstName: "Fatma",
|
firstName: 'Fatma',
|
||||||
lastName: "Çelik",
|
lastName: 'Çelik',
|
||||||
fullName: "Fatma Çelik",
|
fullName: 'Fatma Çelik',
|
||||||
title: "Finans Müdürü",
|
title: 'Finans Müdürü',
|
||||||
email: "fatmacelik@gmail.com",
|
email: 'fatmacelik@gmail.com',
|
||||||
phone: "+90 312 555 3456",
|
phone: '+90 312 555 3456',
|
||||||
department: "Finans",
|
department: 'Finans',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -376,22 +373,22 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
partyType: PartyType.Supplier,
|
partyType: PartyType.Supplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5",
|
id: '5',
|
||||||
code: "CUST-002",
|
code: 'CUST-002',
|
||||||
name: "Üretim Ltd.",
|
name: 'Üretim Ltd.',
|
||||||
customerType: CustomerTypeEnum.Company,
|
customerType: CustomerTypeEnum.Company,
|
||||||
industry: "İmalat",
|
industry: 'İmalat',
|
||||||
website: "www.uretim.com",
|
website: 'www.uretim.com',
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
id: "2",
|
id: '2',
|
||||||
firstName: "Fatma",
|
firstName: 'Fatma',
|
||||||
lastName: "Demir",
|
lastName: 'Demir',
|
||||||
fullName: "Fatma Demir",
|
fullName: 'Fatma Demir',
|
||||||
title: "Genel Müdür",
|
title: 'Genel Müdür',
|
||||||
department: "Yönetim",
|
department: 'Yönetim',
|
||||||
email: "fatma.demir@uretim.com",
|
email: 'fatma.demir@uretim.com',
|
||||||
phone: "+90 312 555 0202",
|
phone: '+90 312 555 0202',
|
||||||
mobile: "+90 532 555 0202",
|
mobile: '+90 532 555 0202',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -399,50 +396,50 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
},
|
},
|
||||||
contacts: [],
|
contacts: [],
|
||||||
address: {
|
address: {
|
||||||
street: "Sanayi Sitesi 5. Cadde No:25",
|
street: 'Sanayi Sitesi 5. Cadde No:25',
|
||||||
city: "Ankara",
|
city: 'Ankara',
|
||||||
state: "Ankara",
|
state: 'Ankara',
|
||||||
postalCode: "06000",
|
postalCode: '06000',
|
||||||
country: "Türkiye",
|
country: 'Türkiye',
|
||||||
},
|
},
|
||||||
taxNumber: "0987654321",
|
taxNumber: '0987654321',
|
||||||
registrationNumber: "REG-002",
|
registrationNumber: 'REG-002',
|
||||||
creditLimit: 500000,
|
creditLimit: 500000,
|
||||||
paymentTerms: PaymentTerms.Net60,
|
paymentTerms: PaymentTerms.Net60,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: BusinessPartyStatusEnum.Active,
|
status: BusinessPartyStatusEnum.Active,
|
||||||
customerSegment: CustomerSegmentEnum.SMB,
|
customerSegment: CustomerSegmentEnum.SMB,
|
||||||
assignedSalesRep: "REP-002",
|
assignedSalesRep: 'REP-002',
|
||||||
teamId: "TEAM-001",
|
teamId: 'TEAM-001',
|
||||||
totalRevenue: 850000,
|
totalRevenue: 850000,
|
||||||
lastOrderDate: new Date("2024-01-10"),
|
lastOrderDate: new Date('2024-01-10'),
|
||||||
averageOrderValue: 42500,
|
averageOrderValue: 42500,
|
||||||
lifetimeValue: 1700000,
|
lifetimeValue: 1700000,
|
||||||
opportunities: [],
|
opportunities: [],
|
||||||
orders: [],
|
orders: [],
|
||||||
activities: [],
|
activities: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-09-20"),
|
creationTime: new Date('2023-09-20'),
|
||||||
lastModificationTime: new Date("2024-01-18"),
|
lastModificationTime: new Date('2024-01-18'),
|
||||||
partyType: PartyType.Customer,
|
partyType: PartyType.Customer,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "6",
|
id: '6',
|
||||||
code: "CUST-001",
|
code: 'CUST-001',
|
||||||
name: "Teknoloji A.Ş.",
|
name: 'Teknoloji A.Ş.',
|
||||||
customerType: CustomerTypeEnum.Company,
|
customerType: CustomerTypeEnum.Company,
|
||||||
industry: "Teknoloji",
|
industry: 'Teknoloji',
|
||||||
website: "www.teknoloji.com",
|
website: 'www.teknoloji.com',
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
id: "1",
|
id: '1',
|
||||||
firstName: "Ali",
|
firstName: 'Ali',
|
||||||
lastName: "Yılmaz",
|
lastName: 'Yılmaz',
|
||||||
fullName: "Ali Yılmaz",
|
fullName: 'Ali Yılmaz',
|
||||||
title: "Satınalma Müdürü",
|
title: 'Satınalma Müdürü',
|
||||||
department: "Satınalma",
|
department: 'Satınalma',
|
||||||
email: "ali.yilmaz@teknoloji.com",
|
email: 'ali.yilmaz@teknoloji.com',
|
||||||
phone: "+90 212 555 0201",
|
phone: '+90 212 555 0201',
|
||||||
mobile: "+90 532 555 0201",
|
mobile: '+90 532 555 0201',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -450,53 +447,53 @@ export const mockBusinessParties: BusinessParty[] = [
|
||||||
},
|
},
|
||||||
contacts: [],
|
contacts: [],
|
||||||
address: {
|
address: {
|
||||||
street: "Teknoloji Caddesi No:100",
|
street: 'Teknoloji Caddesi No:100',
|
||||||
city: "İstanbul",
|
city: 'İstanbul',
|
||||||
state: "İstanbul",
|
state: 'İstanbul',
|
||||||
postalCode: "34000",
|
postalCode: '34000',
|
||||||
country: "Türkiye",
|
country: 'Türkiye',
|
||||||
},
|
},
|
||||||
taxNumber: "1234567890",
|
taxNumber: '1234567890',
|
||||||
registrationNumber: "REG-001",
|
registrationNumber: 'REG-001',
|
||||||
creditLimit: 1000000,
|
creditLimit: 1000000,
|
||||||
paymentTerms: PaymentTerms.Net30,
|
paymentTerms: PaymentTerms.Net30,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: BusinessPartyStatusEnum.Active,
|
status: BusinessPartyStatusEnum.Active,
|
||||||
customerSegment: CustomerSegmentEnum.Enterprise,
|
customerSegment: CustomerSegmentEnum.Enterprise,
|
||||||
assignedSalesRep: "REP-001",
|
assignedSalesRep: 'REP-001',
|
||||||
teamId: "TEAM-001",
|
teamId: 'TEAM-001',
|
||||||
totalRevenue: 2500000,
|
totalRevenue: 2500000,
|
||||||
lastOrderDate: new Date("2024-01-15"),
|
lastOrderDate: new Date('2024-01-15'),
|
||||||
averageOrderValue: 125000,
|
averageOrderValue: 125000,
|
||||||
lifetimeValue: 5000000,
|
lifetimeValue: 5000000,
|
||||||
opportunities: [],
|
opportunities: [],
|
||||||
orders: [],
|
orders: [],
|
||||||
activities: [],
|
activities: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-06-15"),
|
creationTime: new Date('2023-06-15'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
partyType: PartyType.Customer,
|
partyType: PartyType.Customer,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
||||||
export const mockBusinessPartyNew: BusinessParty = {
|
export const mockBusinessPartyNew: BusinessParty = {
|
||||||
id: "",
|
id: '',
|
||||||
code: "",
|
code: '',
|
||||||
supplierType: SupplierTypeEnum.Both,
|
supplierType: SupplierTypeEnum.ServiceProvider,
|
||||||
name: "",
|
name: '',
|
||||||
email: "",
|
email: '',
|
||||||
phone: "",
|
phone: '',
|
||||||
address: {
|
address: {
|
||||||
street: "",
|
street: '',
|
||||||
city: "",
|
city: '',
|
||||||
state: "",
|
state: '',
|
||||||
postalCode: "",
|
postalCode: '',
|
||||||
country: "",
|
country: '',
|
||||||
},
|
},
|
||||||
taxNumber: "",
|
taxNumber: '',
|
||||||
paymentTerms: PaymentTerms.Cash,
|
paymentTerms: PaymentTerms.Cash,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
cardNumber: "",
|
cardNumber: '',
|
||||||
cardType: SupplierCardTypeEnum.Standard,
|
cardType: SupplierCardTypeEnum.Standard,
|
||||||
validTo: new Date(),
|
validTo: new Date(),
|
||||||
validFrom: new Date(),
|
validFrom: new Date(),
|
||||||
|
|
@ -521,4 +518,4 @@ export const mockBusinessPartyNew: BusinessParty = {
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
partyType: PartyType.Supplier,
|
partyType: PartyType.Supplier,
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,44 @@
|
||||||
import { FiCheck, CheckStatusEnum, CheckTypeEnum } from "../types/fi";
|
import { FiCheck, CheckStatusEnum, TypeEnum } from '../types/fi'
|
||||||
import { mockCurrentAccounts } from "./mockCurrentAccounts";
|
import { mockCurrentAccounts } from './mockCurrentAccounts'
|
||||||
|
|
||||||
export const mockChecks: FiCheck[] = [
|
export const mockChecks: FiCheck[] = [
|
||||||
{
|
{
|
||||||
id: "1",
|
id: '1',
|
||||||
checkNumber: "CHK-001",
|
checkNumber: 'CHK-001',
|
||||||
bankName: "İş Bankası",
|
bankName: 'İş Bankası',
|
||||||
branchName: "Levent Şubesi",
|
branchName: 'Levent Şubesi',
|
||||||
accountNumber: "1234567890",
|
accountNumber: '1234567890',
|
||||||
type: CheckTypeEnum.Received,
|
type: TypeEnum.Received,
|
||||||
drawerName: "XYZ Müşteri A.Ş.",
|
drawerName: 'XYZ Müşteri A.Ş.',
|
||||||
payeeName: "ABC Şirket",
|
payeeName: 'ABC Şirket',
|
||||||
issueDate: new Date("2024-01-15"),
|
issueDate: new Date('2024-01-15'),
|
||||||
dueDate: new Date("2024-02-15"),
|
dueDate: new Date('2024-02-15'),
|
||||||
amount: 25000,
|
amount: 25000,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: CheckStatusEnum.InHand,
|
status: CheckStatusEnum.InHand,
|
||||||
currentAccountId: "1",
|
currentAccountId: '1',
|
||||||
currentAccount: mockCurrentAccounts.find((ca) => ca.id === "1"),
|
currentAccount: mockCurrentAccounts.find((ca) => ca.id === '1'),
|
||||||
creationTime: new Date("2024-01-15"),
|
creationTime: new Date('2024-01-15'),
|
||||||
lastModificationTime: new Date("2024-01-15"),
|
lastModificationTime: new Date('2024-01-15'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: '2',
|
||||||
checkNumber: "CHK-002",
|
checkNumber: 'CHK-002',
|
||||||
bankName: "Garanti BBVA",
|
bankName: 'Garanti BBVA',
|
||||||
branchName: "Şişli Şubesi",
|
branchName: 'Şişli Şubesi',
|
||||||
accountNumber: "9876543210",
|
accountNumber: '9876543210',
|
||||||
type: CheckTypeEnum.Issued,
|
type: TypeEnum.Issued,
|
||||||
drawerName: "ABC Şirket",
|
drawerName: 'ABC Şirket',
|
||||||
payeeName: "Tedarikçi Ltd.",
|
payeeName: 'Tedarikçi Ltd.',
|
||||||
issueDate: new Date("2024-01-10"),
|
issueDate: new Date('2024-01-10'),
|
||||||
dueDate: new Date("2024-02-10"),
|
dueDate: new Date('2024-02-10'),
|
||||||
amount: 15000,
|
amount: 15000,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: CheckStatusEnum.Deposited,
|
status: CheckStatusEnum.Deposited,
|
||||||
bankingDate: new Date("2024-01-20"),
|
bankingDate: new Date('2024-01-20'),
|
||||||
currentAccountId: "2",
|
currentAccountId: '2',
|
||||||
currentAccount: mockCurrentAccounts.find((ca) => ca.id === "2"),
|
currentAccount: mockCurrentAccounts.find((ca) => ca.id === '2'),
|
||||||
creationTime: new Date("2024-01-10"),
|
creationTime: new Date('2024-01-10'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,80 @@
|
||||||
import { PsProjectCostTracking } from "../types/ps";
|
import { ProjectCostTrackingStatus, PsProjectCostTracking } from '../types/ps'
|
||||||
|
|
||||||
export const mockProjectCostTracking: PsProjectCostTracking[] = [
|
export const mockProjectCostTracking: PsProjectCostTracking[] = [
|
||||||
{
|
{
|
||||||
id: "1",
|
id: '1',
|
||||||
projectId: "1",
|
projectId: '1',
|
||||||
projectName: "ERP Sistemi Geliştirme",
|
projectName: 'ERP Sistemi Geliştirme',
|
||||||
projectCode: "PRJ-2024-001",
|
projectCode: 'PRJ-2024-001',
|
||||||
plannedBudget: 500000,
|
plannedBudget: 500000,
|
||||||
actualCost: 325000,
|
actualCost: 325000,
|
||||||
remainingBudget: 175000,
|
remainingBudget: 175000,
|
||||||
plannedStartDate: new Date("2024-01-15"),
|
plannedStartDate: new Date('2024-01-15'),
|
||||||
plannedEndDate: new Date("2024-12-31"),
|
plannedEndDate: new Date('2024-12-31'),
|
||||||
actualStartDate: new Date("2024-01-20"),
|
actualStartDate: new Date('2024-01-20'),
|
||||||
actualEndDate: undefined,
|
actualEndDate: undefined,
|
||||||
plannedDuration: 351,
|
plannedDuration: 351,
|
||||||
actualDuration: 300,
|
actualDuration: 300,
|
||||||
progress: 65,
|
progress: 65,
|
||||||
status: "ON_TRACK",
|
status: ProjectCostTrackingStatus.OnTrack,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
lastUpdated: new Date("2024-11-25"),
|
lastUpdated: new Date('2024-11-25'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: '2',
|
||||||
projectId: "2",
|
projectId: '2',
|
||||||
projectName: "Mobil Uygulama Geliştirme",
|
projectName: 'Mobil Uygulama Geliştirme',
|
||||||
projectCode: "PRJ-2024-002",
|
projectCode: 'PRJ-2024-002',
|
||||||
plannedBudget: 250000,
|
plannedBudget: 250000,
|
||||||
actualCost: 200000,
|
actualCost: 200000,
|
||||||
remainingBudget: 50000,
|
remainingBudget: 50000,
|
||||||
plannedStartDate: new Date("2024-03-01"),
|
plannedStartDate: new Date('2024-03-01'),
|
||||||
plannedEndDate: new Date("2024-08-31"),
|
plannedEndDate: new Date('2024-08-31'),
|
||||||
actualStartDate: new Date("2024-03-15"),
|
actualStartDate: new Date('2024-03-15'),
|
||||||
actualEndDate: undefined,
|
actualEndDate: undefined,
|
||||||
plannedDuration: 184,
|
plannedDuration: 184,
|
||||||
actualDuration: 200,
|
actualDuration: 200,
|
||||||
progress: 80,
|
progress: 80,
|
||||||
status: "AT_RISK",
|
status: ProjectCostTrackingStatus.AtRisk,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
lastUpdated: new Date("2024-11-20"),
|
lastUpdated: new Date('2024-11-20'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "3",
|
id: '3',
|
||||||
projectId: "3",
|
projectId: '3',
|
||||||
projectName: "Web Sitesi Yenileme",
|
projectName: 'Web Sitesi Yenileme',
|
||||||
projectCode: "PRJ-2024-003",
|
projectCode: 'PRJ-2024-003',
|
||||||
plannedBudget: 150000,
|
plannedBudget: 150000,
|
||||||
actualCost: 180000,
|
actualCost: 180000,
|
||||||
remainingBudget: -30000,
|
remainingBudget: -30000,
|
||||||
plannedStartDate: new Date("2024-02-01"),
|
plannedStartDate: new Date('2024-02-01'),
|
||||||
plannedEndDate: new Date("2024-06-30"),
|
plannedEndDate: new Date('2024-06-30'),
|
||||||
actualStartDate: new Date("2024-02-10"),
|
actualStartDate: new Date('2024-02-10'),
|
||||||
actualEndDate: new Date("2024-07-15"),
|
actualEndDate: new Date('2024-07-15'),
|
||||||
plannedDuration: 150,
|
plannedDuration: 150,
|
||||||
actualDuration: 156,
|
actualDuration: 156,
|
||||||
progress: 100,
|
progress: 100,
|
||||||
status: "COMPLETED",
|
status: ProjectCostTrackingStatus.Completed,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
lastUpdated: new Date("2024-07-15"),
|
lastUpdated: new Date('2024-07-15'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4",
|
id: '4',
|
||||||
projectId: "4",
|
projectId: '4',
|
||||||
projectName: "Veri Analizi Platformu",
|
projectName: 'Veri Analizi Platformu',
|
||||||
projectCode: "PRJ-2024-004",
|
projectCode: 'PRJ-2024-004',
|
||||||
plannedBudget: 400000,
|
plannedBudget: 400000,
|
||||||
actualCost: 120000,
|
actualCost: 120000,
|
||||||
remainingBudget: 280000,
|
remainingBudget: 280000,
|
||||||
plannedStartDate: new Date("2024-06-01"),
|
plannedStartDate: new Date('2024-06-01'),
|
||||||
plannedEndDate: new Date("2024-12-31"),
|
plannedEndDate: new Date('2024-12-31'),
|
||||||
actualStartDate: new Date("2024-06-15"),
|
actualStartDate: new Date('2024-06-15'),
|
||||||
actualEndDate: undefined,
|
actualEndDate: undefined,
|
||||||
plannedDuration: 214,
|
plannedDuration: 214,
|
||||||
actualDuration: 163,
|
actualDuration: 163,
|
||||||
progress: 30,
|
progress: 30,
|
||||||
status: "DELAYED",
|
status: ProjectCostTrackingStatus.Delayed,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
lastUpdated: new Date("2024-11-22"),
|
lastUpdated: new Date('2024-11-22'),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,180 +1,164 @@
|
||||||
import { PhaseStatusEnum, PsProjectPhase } from "../types/ps";
|
import { PhaseCategoryEnum, PhaseStatusEnum, PsProjectPhase } from '../types/ps'
|
||||||
import { mockMaintenanceTeams } from "./mockMaintenanceTeams";
|
import { mockMaintenanceTeams } from './mockMaintenanceTeams'
|
||||||
import { mockProjects } from "./mockProjects";
|
import { mockProjects } from './mockProjects'
|
||||||
|
|
||||||
export const mockProjectPhases: PsProjectPhase[] = [
|
export const mockProjectPhases: PsProjectPhase[] = [
|
||||||
{
|
{
|
||||||
id: "1",
|
id: '1',
|
||||||
code: "PH-001",
|
code: 'PH-001',
|
||||||
name: "Analiz ve Tasarım",
|
name: 'Analiz ve Tasarım',
|
||||||
description: "Sistem analizi ve tasarım dokümantasyonu hazırlanması",
|
description: 'Sistem analizi ve tasarım dokümantasyonu hazırlanması',
|
||||||
projectId: "1",
|
projectId: '1',
|
||||||
project: mockProjects.find((p) => p.id === "1")!,
|
project: mockProjects.find((p) => p.id === '1')!,
|
||||||
status: PhaseStatusEnum.Completed,
|
status: PhaseStatusEnum.Completed,
|
||||||
startDate: new Date("2024-01-15"),
|
startDate: new Date('2024-01-15'),
|
||||||
endDate: new Date("2024-02-28"),
|
endDate: new Date('2024-02-28'),
|
||||||
actualStartDate: new Date("2024-01-15"),
|
actualStartDate: new Date('2024-01-15'),
|
||||||
actualEndDate: new Date("2024-02-25"),
|
actualEndDate: new Date('2024-02-25'),
|
||||||
budget: 150000,
|
budget: 150000,
|
||||||
actualCost: 145000,
|
actualCost: 145000,
|
||||||
progress: 100,
|
progress: 100,
|
||||||
milestones: 4,
|
milestones: 4,
|
||||||
completedMilestones: 4,
|
completedMilestones: 4,
|
||||||
assignedTeams: [
|
assignedTeams: [
|
||||||
mockMaintenanceTeams.find((t) => t.id === "1")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '1')!.name,
|
||||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||||
],
|
],
|
||||||
deliverables: [
|
deliverables: ['Sistem Analiz Raporu', 'Teknik Tasarım Dokümanı', 'UI/UX Tasarımları'],
|
||||||
"Sistem Analiz Raporu",
|
risks: ['Gereksinim değişiklikleri'],
|
||||||
"Teknik Tasarım Dokümanı",
|
category: PhaseCategoryEnum.Planning,
|
||||||
"UI/UX Tasarımları",
|
|
||||||
],
|
|
||||||
risks: ["Gereksinim değişiklikleri"],
|
|
||||||
category: "Planning",
|
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: '2',
|
||||||
code: "PH-002",
|
code: 'PH-002',
|
||||||
name: "Geliştirme - Faz 1",
|
name: 'Geliştirme - Faz 1',
|
||||||
description: "Backend altyapısı ve temel modüllerin geliştirilmesi",
|
description: 'Backend altyapısı ve temel modüllerin geliştirilmesi',
|
||||||
projectId: "1",
|
projectId: '1',
|
||||||
project: mockProjects.find((p) => p.id === "1")!,
|
project: mockProjects.find((p) => p.id === '1')!,
|
||||||
status: PhaseStatusEnum.Cancelled,
|
status: PhaseStatusEnum.Cancelled,
|
||||||
startDate: new Date("2024-03-01"),
|
startDate: new Date('2024-03-01'),
|
||||||
endDate: new Date("2024-05-15"),
|
endDate: new Date('2024-05-15'),
|
||||||
actualStartDate: new Date("2024-03-01"),
|
actualStartDate: new Date('2024-03-01'),
|
||||||
actualEndDate: new Date("2024-05-10"),
|
actualEndDate: new Date('2024-05-10'),
|
||||||
budget: 400000,
|
budget: 400000,
|
||||||
actualCost: 280000,
|
actualCost: 280000,
|
||||||
progress: 70,
|
progress: 70,
|
||||||
milestones: 6,
|
milestones: 6,
|
||||||
completedMilestones: 4,
|
completedMilestones: 4,
|
||||||
assignedTeams: [
|
assignedTeams: [
|
||||||
mockMaintenanceTeams.find((t) => t.id === "1")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '1')!.name,
|
||||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||||
],
|
],
|
||||||
deliverables: ["API Framework", "Veritabanı Şeması", "Güvenlik Modülü"],
|
deliverables: ['API Framework', 'Veritabanı Şeması', 'Güvenlik Modülü'],
|
||||||
risks: ["Performans sorunları", "Üçüncü parti entegrasyon gecikmeleri"],
|
risks: ['Performans sorunları', 'Üçüncü parti entegrasyon gecikmeleri'],
|
||||||
category: "Development",
|
category: PhaseCategoryEnum.Development,
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "3",
|
id: '3',
|
||||||
code: "PH-003",
|
code: 'PH-003',
|
||||||
name: "Geliştirme - Faz 2",
|
name: 'Geliştirme - Faz 2',
|
||||||
description: "Frontend geliştirme ve kullanıcı arayüzleri",
|
description: 'Frontend geliştirme ve kullanıcı arayüzleri',
|
||||||
projectId: "1",
|
projectId: '1',
|
||||||
project: mockProjects.find((p) => p.id === "1")!,
|
project: mockProjects.find((p) => p.id === '1')!,
|
||||||
status: PhaseStatusEnum.NotStarted,
|
status: PhaseStatusEnum.NotStarted,
|
||||||
startDate: new Date("2024-04-15"),
|
startDate: new Date('2024-04-15'),
|
||||||
endDate: new Date("2024-07-30"),
|
endDate: new Date('2024-07-30'),
|
||||||
budget: 350000,
|
budget: 350000,
|
||||||
actualCost: 0,
|
actualCost: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
milestones: 5,
|
milestones: 5,
|
||||||
completedMilestones: 0,
|
completedMilestones: 0,
|
||||||
assignedTeams: [
|
assignedTeams: [
|
||||||
mockMaintenanceTeams.find((t) => t.id === "1")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '1')!.name,
|
||||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||||
],
|
],
|
||||||
deliverables: [
|
deliverables: ['React Bileşenleri', 'Responsive Tasarım', 'Mobil Uyumluluk'],
|
||||||
"React Bileşenleri",
|
risks: ['Tarayıcı uyumluluk sorunları', 'Performans optimizasyonu'],
|
||||||
"Responsive Tasarım",
|
category: PhaseCategoryEnum.Development,
|
||||||
"Mobil Uyumluluk",
|
|
||||||
],
|
|
||||||
risks: ["Tarayıcı uyumluluk sorunları", "Performans optimizasyonu"],
|
|
||||||
category: "Development",
|
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4",
|
id: '4',
|
||||||
code: "PH-004",
|
code: 'PH-004',
|
||||||
name: "Test ve Kalite Güvence",
|
name: 'Test ve Kalite Güvence',
|
||||||
description: "Kapsamlı test süreçleri ve kalite kontrolleri",
|
description: 'Kapsamlı test süreçleri ve kalite kontrolleri',
|
||||||
projectId: "2",
|
projectId: '2',
|
||||||
project: mockProjects.find((p) => p.id === "2")!,
|
project: mockProjects.find((p) => p.id === '2')!,
|
||||||
status: PhaseStatusEnum.NotStarted,
|
status: PhaseStatusEnum.NotStarted,
|
||||||
startDate: new Date("2024-07-01"),
|
startDate: new Date('2024-07-01'),
|
||||||
endDate: new Date("2024-09-15"),
|
endDate: new Date('2024-09-15'),
|
||||||
budget: 120000,
|
budget: 120000,
|
||||||
actualCost: 0,
|
actualCost: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
milestones: 3,
|
milestones: 3,
|
||||||
completedMilestones: 0,
|
completedMilestones: 0,
|
||||||
assignedTeams: [
|
assignedTeams: [
|
||||||
mockMaintenanceTeams.find((t) => t.id === "3")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '3')!.name,
|
||||||
mockMaintenanceTeams.find((t) => t.id === "4")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '4')!.name,
|
||||||
],
|
],
|
||||||
deliverables: [
|
deliverables: ['Test Senaryoları', 'Otomatik Test Süitleri', 'Kalite Raporu'],
|
||||||
"Test Senaryoları",
|
risks: ['Kritik hataların geç tespit edilmesi'],
|
||||||
"Otomatik Test Süitleri",
|
category: PhaseCategoryEnum.Testing,
|
||||||
"Kalite Raporu",
|
|
||||||
],
|
|
||||||
risks: ["Kritik hataların geç tespit edilmesi"],
|
|
||||||
category: "Testing",
|
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5",
|
id: '5',
|
||||||
code: "PH-005",
|
code: 'PH-005',
|
||||||
name: "Deployment ve Go-Live",
|
name: 'Deployment ve Go-Live',
|
||||||
description: "Üretime alma ve kullanıcı eğitimleri",
|
description: 'Üretime alma ve kullanıcı eğitimleri',
|
||||||
projectId: "2",
|
projectId: '2',
|
||||||
project: mockProjects.find((p) => p.id === "2")!,
|
project: mockProjects.find((p) => p.id === '2')!,
|
||||||
status: PhaseStatusEnum.NotStarted,
|
status: PhaseStatusEnum.NotStarted,
|
||||||
startDate: new Date("2024-09-15"),
|
startDate: new Date('2024-09-15'),
|
||||||
endDate: new Date("2024-10-31"),
|
endDate: new Date('2024-10-31'),
|
||||||
budget: 80000,
|
budget: 80000,
|
||||||
actualCost: 0,
|
actualCost: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
milestones: 2,
|
milestones: 2,
|
||||||
completedMilestones: 0,
|
completedMilestones: 0,
|
||||||
assignedTeams: [
|
assignedTeams: [
|
||||||
mockMaintenanceTeams.find((t) => t.id === "2")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '2')!.name,
|
||||||
mockMaintenanceTeams.find((t) => t.id === "4")!.name,
|
mockMaintenanceTeams.find((t) => t.id === '4')!.name,
|
||||||
],
|
],
|
||||||
deliverables: [
|
deliverables: ['Prodüksiyon Ortamı', 'Kullanıcı Eğitimleri', 'Dokümentasyon'],
|
||||||
"Prodüksiyon Ortamı",
|
risks: ['Sistem kesintileri', 'Kullanıcı adaptasyon sorunları'],
|
||||||
"Kullanıcı Eğitimleri",
|
category: PhaseCategoryEnum.Deployment,
|
||||||
"Dokümentasyon",
|
|
||||||
],
|
|
||||||
risks: ["Sistem kesintileri", "Kullanıcı adaptasyon sorunları"],
|
|
||||||
category: "Deployment",
|
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "6",
|
id: '6',
|
||||||
code: "PH-006",
|
code: 'PH-006',
|
||||||
name: "Mobil UI Tasarımı",
|
name: 'Mobil UI Tasarımı',
|
||||||
description: "Mobil uygulama kullanıcı arayüzü tasarımı",
|
description: 'Mobil uygulama kullanıcı arayüzü tasarımı',
|
||||||
projectId: "2",
|
projectId: '2',
|
||||||
project: mockProjects.find((p) => p.id === "2")!,
|
project: mockProjects.find((p) => p.id === '2')!,
|
||||||
status: PhaseStatusEnum.OnHold,
|
status: PhaseStatusEnum.OnHold,
|
||||||
startDate: new Date("2024-03-01"),
|
startDate: new Date('2024-03-01'),
|
||||||
endDate: new Date("2024-04-15"),
|
endDate: new Date('2024-04-15'),
|
||||||
actualStartDate: new Date("2024-03-05"),
|
actualStartDate: new Date('2024-03-05'),
|
||||||
budget: 75000,
|
budget: 75000,
|
||||||
actualCost: 25000,
|
actualCost: 25000,
|
||||||
progress: 35,
|
progress: 35,
|
||||||
milestones: 3,
|
milestones: 3,
|
||||||
completedMilestones: 1,
|
completedMilestones: 1,
|
||||||
assignedTeams: [mockMaintenanceTeams.find((t) => t.id === "1")!.name],
|
assignedTeams: [mockMaintenanceTeams.find((t) => t.id === '1')!.name],
|
||||||
deliverables: ["Wireframe'ler", "Mobil Tasarım Kılavuzu", "Prototype"],
|
deliverables: ["Wireframe'ler", 'Mobil Tasarım Kılavuzu', 'Prototype'],
|
||||||
risks: ["Platformlar arası tutarlılık sorunları"],
|
risks: ['Platformlar arası tutarlılık sorunları'],
|
||||||
category: "Design",
|
category: PhaseCategoryEnum.Design,
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,40 @@
|
||||||
import { NoteStatusEnum, NoteTypeEnum, PromissoryNote } from "../types/fi";
|
import { NoteStatusEnum, PromissoryNote, TypeEnum } from '../types/fi'
|
||||||
import { mockCurrentAccounts } from "./mockCurrentAccounts";
|
import { mockCurrentAccounts } from './mockCurrentAccounts'
|
||||||
|
|
||||||
export const mockPromissoryNotes: PromissoryNote[] = [
|
export const mockPromissoryNotes: PromissoryNote[] = [
|
||||||
{
|
{
|
||||||
id: "1",
|
id: '1',
|
||||||
noteNumber: "NOT-001",
|
noteNumber: 'NOT-001',
|
||||||
type: NoteTypeEnum.Received,
|
type: TypeEnum.Received,
|
||||||
drawerName: "Müşteri A.Ş.",
|
drawerName: 'Müşteri A.Ş.',
|
||||||
payeeName: "ABC Şirket",
|
payeeName: 'ABC Şirket',
|
||||||
issueDate: new Date("2024-01-20"),
|
issueDate: new Date('2024-01-20'),
|
||||||
dueDate: new Date("2024-03-20"),
|
dueDate: new Date('2024-03-20'),
|
||||||
amount: 50000,
|
amount: 50000,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: NoteStatusEnum.InHand,
|
status: NoteStatusEnum.InHand,
|
||||||
location: "Ana Kasa",
|
location: 'Ana Kasa',
|
||||||
currentAccountId: "1",
|
currentAccountId: '1',
|
||||||
currentAccount: mockCurrentAccounts.find((acc) => acc.id === "1"),
|
currentAccount: mockCurrentAccounts.find((acc) => acc.id === '1'),
|
||||||
creationTime: new Date("2024-01-20"),
|
creationTime: new Date('2024-01-20'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: '2',
|
||||||
noteNumber: "NOT-002",
|
noteNumber: 'NOT-002',
|
||||||
type: NoteTypeEnum.Issued,
|
type: TypeEnum.Issued,
|
||||||
drawerName: "ABC Şirket",
|
drawerName: 'ABC Şirket',
|
||||||
payeeName: "Kefil A.Ş.",
|
payeeName: 'Kefil A.Ş.',
|
||||||
issueDate: new Date("2024-01-05"),
|
issueDate: new Date('2024-01-05'),
|
||||||
dueDate: new Date("2024-03-05"),
|
dueDate: new Date('2024-03-05'),
|
||||||
amount: 30000,
|
amount: 30000,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: NoteStatusEnum.Collected,
|
status: NoteStatusEnum.Collected,
|
||||||
location: "Banka",
|
location: 'Banka',
|
||||||
collectionDate: new Date("2024-01-25"),
|
collectionDate: new Date('2024-01-25'),
|
||||||
currentAccountId: "2",
|
currentAccountId: '2',
|
||||||
currentAccount: mockCurrentAccounts.find((acc) => acc.id === "2"),
|
currentAccount: mockCurrentAccounts.find((acc) => acc.id === '2'),
|
||||||
creationTime: new Date("2024-01-05"),
|
creationTime: new Date('2024-01-05'),
|
||||||
lastModificationTime: new Date("2024-01-25"),
|
lastModificationTime: new Date('2024-01-25'),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
|
||||||
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 {
|
import { CriticalityLevelEnum, PmWorkCenter, WorkCenterStatusEnum } from '../types/pm'
|
||||||
CriticalityLevelEnum,
|
import { mockWorkCenterMachineTypes } from './mockWorkCenterMachineTypes'
|
||||||
PmWorkCenter,
|
import { mockWorkCenterTypes } from './mockWorkCenterTypes'
|
||||||
WorkCenterStatusEnum,
|
|
||||||
} from "../types/pm";
|
|
||||||
import { mockWorkCenterTypes } from "./mockWorkCenterTypes";
|
|
||||||
|
|
||||||
export const mockWorkCenters: PmWorkCenter[] = [
|
export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
{
|
{
|
||||||
id: "1",
|
id: '1',
|
||||||
code: "CNC-001",
|
code: 'CNC-001',
|
||||||
name: "CNC Torna Tezgahı",
|
name: 'CNC Torna Tezgahı',
|
||||||
description: "Yüksek hassasiyetli CNC torna tezgahı",
|
description: 'Yüksek hassasiyetli CNC torna tezgahı',
|
||||||
workCenterId: "1",
|
workCenterId: '1',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "1")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '1')!,
|
||||||
manufacturer: "HAAS Automation",
|
manufacturer: 'HAAS Automation',
|
||||||
model: "ST-30",
|
model: 'ST-30',
|
||||||
serialNumber: "SN123456789",
|
serialNumber: 'SN123456789',
|
||||||
installationDate: new Date("2022-03-15"),
|
installationDate: new Date('2022-03-15'),
|
||||||
warrantyExpiry: new Date("2025-03-15"),
|
warrantyExpiry: new Date('2025-03-15'),
|
||||||
location: "Atölye A - Hat 1",
|
location: 'Atölye A - Hat 1',
|
||||||
departmentId: "1",
|
departmentId: '1',
|
||||||
status: WorkCenterStatusEnum.Operational,
|
status: WorkCenterStatusEnum.Operational,
|
||||||
criticality: CriticalityLevelEnum.High,
|
criticality: CriticalityLevelEnum.High,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC001",
|
id: 'SPEC001',
|
||||||
workCenterId: "EQP001",
|
workCenterId: 'EQP001',
|
||||||
specificationName: "Max Çap",
|
specificationName: 'Max Çap',
|
||||||
specificationValue: "300",
|
specificationValue: '300',
|
||||||
unit: "mm",
|
unit: 'mm',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC002",
|
id: 'SPEC002',
|
||||||
workCenterId: "EQP001",
|
workCenterId: 'EQP001',
|
||||||
specificationName: "Motor Gücü",
|
specificationName: 'Motor Gücü',
|
||||||
specificationValue: "15",
|
specificationValue: '15',
|
||||||
unit: "kW",
|
unit: 'kW',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -44,44 +41,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2022-03-15"),
|
creationTime: new Date('2022-03-15'),
|
||||||
lastModificationTime: new Date("2024-01-15"),
|
lastModificationTime: new Date('2024-01-15'),
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
costPerHour: 75,
|
costPerHour: 75,
|
||||||
setupTime: 15,
|
setupTime: 15,
|
||||||
machineType: "CNC",
|
machineTypeId: '1',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: '2',
|
||||||
code: "COMP-001",
|
code: 'COMP-001',
|
||||||
name: "Hava Kompresörü",
|
name: 'Hava Kompresörü',
|
||||||
description: "Endüstriyel hava kompresörü sistemi",
|
description: 'Endüstriyel hava kompresörü sistemi',
|
||||||
workCenterId: "2",
|
workCenterId: '2',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "2")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '2')!,
|
||||||
manufacturer: "Atlas Copco",
|
manufacturer: 'Atlas Copco',
|
||||||
model: "GA55VSD+",
|
model: 'GA55VSD+',
|
||||||
serialNumber: "AC987654321",
|
serialNumber: 'AC987654321',
|
||||||
installationDate: new Date("2021-08-20"),
|
installationDate: new Date('2021-08-20'),
|
||||||
warrantyExpiry: new Date("2024-08-20"),
|
warrantyExpiry: new Date('2024-08-20'),
|
||||||
location: "Kompresör Odası",
|
location: 'Kompresör Odası',
|
||||||
departmentId: "2",
|
departmentId: '2',
|
||||||
status: WorkCenterStatusEnum.UnderMaintenance,
|
status: WorkCenterStatusEnum.UnderMaintenance,
|
||||||
criticality: CriticalityLevelEnum.Critical,
|
criticality: CriticalityLevelEnum.Critical,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC003",
|
id: 'SPEC003',
|
||||||
workCenterId: "EQP002",
|
workCenterId: 'EQP002',
|
||||||
specificationName: "Basınç",
|
specificationName: 'Basınç',
|
||||||
specificationValue: "8.5",
|
specificationValue: '8.5',
|
||||||
unit: "bar",
|
unit: 'bar',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC004",
|
id: 'SPEC004',
|
||||||
workCenterId: "EQP002",
|
workCenterId: 'EQP002',
|
||||||
specificationName: "Kapasite",
|
specificationName: 'Kapasite',
|
||||||
specificationValue: "55",
|
specificationValue: '55',
|
||||||
unit: "kW",
|
unit: 'kW',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -89,43 +87,44 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2021-08-20"),
|
creationTime: new Date('2021-08-20'),
|
||||||
lastModificationTime: new Date("2024-02-01"),
|
lastModificationTime: new Date('2024-02-01'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '2',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '2')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "3",
|
id: '3',
|
||||||
code: "CONV-001",
|
code: 'CONV-001',
|
||||||
name: "Konveyör Sistemi",
|
name: 'Konveyör Sistemi',
|
||||||
description: "Ana hat konveyör sistemi",
|
description: 'Ana hat konveyör sistemi',
|
||||||
workCenterId: "3",
|
workCenterId: '3',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "3")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '3')!,
|
||||||
manufacturer: "Siemens",
|
manufacturer: 'Siemens',
|
||||||
model: "SIMATIC S7-1500",
|
model: 'SIMATIC S7-1500',
|
||||||
serialNumber: "SM112233445",
|
serialNumber: 'SM112233445',
|
||||||
installationDate: new Date("2020-11-10"),
|
installationDate: new Date('2020-11-10'),
|
||||||
location: "Ana Üretim Hattı",
|
location: 'Ana Üretim Hattı',
|
||||||
departmentId: "3",
|
departmentId: '3',
|
||||||
status: WorkCenterStatusEnum.OutOfOrder,
|
status: WorkCenterStatusEnum.OutOfOrder,
|
||||||
criticality: CriticalityLevelEnum.Medium,
|
criticality: CriticalityLevelEnum.Medium,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC005",
|
id: 'SPEC005',
|
||||||
workCenterId: "EQP003",
|
workCenterId: 'EQP003',
|
||||||
specificationName: "Hız",
|
specificationName: 'Hız',
|
||||||
specificationValue: "2.5",
|
specificationValue: '2.5',
|
||||||
unit: "m/s",
|
unit: 'm/s',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC006",
|
id: 'SPEC006',
|
||||||
workCenterId: "EQP003",
|
workCenterId: 'EQP003',
|
||||||
specificationName: "Yük Kapasitesi",
|
specificationName: 'Yük Kapasitesi',
|
||||||
specificationValue: "500",
|
specificationValue: '500',
|
||||||
unit: "kg",
|
unit: 'kg',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -133,44 +132,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2020-11-10"),
|
creationTime: new Date('2020-11-10'),
|
||||||
lastModificationTime: new Date("2024-02-05"),
|
lastModificationTime: new Date('2024-02-05'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '3',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '3')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4",
|
id: '4',
|
||||||
code: "KELD-001",
|
code: 'KELD-001',
|
||||||
name: "Kaynak Makinesi",
|
name: 'Kaynak Makinesi',
|
||||||
description: "Otomatik robot kaynak sistemi",
|
description: 'Otomatik robot kaynak sistemi',
|
||||||
workCenterId: "4",
|
workCenterId: '4',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||||
manufacturer: "KUKA",
|
manufacturer: 'KUKA',
|
||||||
model: "KR 60-3",
|
model: 'KR 60-3',
|
||||||
serialNumber: "KU556677889",
|
serialNumber: 'KU556677889',
|
||||||
installationDate: new Date("2023-01-15"),
|
installationDate: new Date('2023-01-15'),
|
||||||
warrantyExpiry: new Date("2026-01-15"),
|
warrantyExpiry: new Date('2026-01-15'),
|
||||||
location: "Kaynak Atölyesi",
|
location: 'Kaynak Atölyesi',
|
||||||
departmentId: "4",
|
departmentId: '4',
|
||||||
status: WorkCenterStatusEnum.Operational,
|
status: WorkCenterStatusEnum.Operational,
|
||||||
criticality: CriticalityLevelEnum.High,
|
criticality: CriticalityLevelEnum.High,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC007",
|
id: 'SPEC007',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Erişim Mesafesi",
|
specificationName: 'Erişim Mesafesi',
|
||||||
specificationValue: "2033",
|
specificationValue: '2033',
|
||||||
unit: "mm",
|
unit: 'mm',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC008",
|
id: 'SPEC008',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Taşıma Kapasitesi",
|
specificationName: 'Taşıma Kapasitesi',
|
||||||
specificationValue: "60",
|
specificationValue: '60',
|
||||||
unit: "kg",
|
unit: 'kg',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -178,44 +178,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-01-15"),
|
creationTime: new Date('2023-01-15'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '3',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '3')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5",
|
id: '5',
|
||||||
code: "WELL-001",
|
code: 'WELL-001',
|
||||||
name: "Yıkama Makinesi",
|
name: 'Yıkama Makinesi',
|
||||||
description: "Otomatik robot kaynak sistemi",
|
description: 'Otomatik robot kaynak sistemi',
|
||||||
workCenterId: "4",
|
workCenterId: '4',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||||
manufacturer: "KUKA",
|
manufacturer: 'KUKA',
|
||||||
model: "KR 60-3",
|
model: 'KR 60-3',
|
||||||
serialNumber: "KU556677889",
|
serialNumber: 'KU556677889',
|
||||||
installationDate: new Date("2023-01-15"),
|
installationDate: new Date('2023-01-15'),
|
||||||
warrantyExpiry: new Date("2026-01-15"),
|
warrantyExpiry: new Date('2026-01-15'),
|
||||||
location: "Kaynak Atölyesi",
|
location: 'Kaynak Atölyesi',
|
||||||
departmentId: "4",
|
departmentId: '4',
|
||||||
status: WorkCenterStatusEnum.Operational,
|
status: WorkCenterStatusEnum.Operational,
|
||||||
criticality: CriticalityLevelEnum.High,
|
criticality: CriticalityLevelEnum.High,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC007",
|
id: 'SPEC007',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Erişim Mesafesi",
|
specificationName: 'Erişim Mesafesi',
|
||||||
specificationValue: "2033",
|
specificationValue: '2033',
|
||||||
unit: "mm",
|
unit: 'mm',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC008",
|
id: 'SPEC008',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Taşıma Kapasitesi",
|
specificationName: 'Taşıma Kapasitesi',
|
||||||
specificationValue: "60",
|
specificationValue: '60',
|
||||||
unit: "kg",
|
unit: 'kg',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -223,44 +224,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-01-15"),
|
creationTime: new Date('2023-01-15'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '4',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '4')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "6",
|
id: '6',
|
||||||
code: "KELD-001",
|
code: 'KELD-001',
|
||||||
name: "Ram Makinesi",
|
name: 'Ram Makinesi',
|
||||||
description: "Otomatik robot kaynak sistemi",
|
description: 'Otomatik robot kaynak sistemi',
|
||||||
workCenterId: "4",
|
workCenterId: '4',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||||
manufacturer: "KUKA",
|
manufacturer: 'KUKA',
|
||||||
model: "KR 60-3",
|
model: 'KR 60-3',
|
||||||
serialNumber: "KU556677889",
|
serialNumber: 'KU556677889',
|
||||||
installationDate: new Date("2023-01-15"),
|
installationDate: new Date('2023-01-15'),
|
||||||
warrantyExpiry: new Date("2026-01-15"),
|
warrantyExpiry: new Date('2026-01-15'),
|
||||||
location: "Kaynak Atölyesi",
|
location: 'Kaynak Atölyesi',
|
||||||
departmentId: "4",
|
departmentId: '4',
|
||||||
status: WorkCenterStatusEnum.Operational,
|
status: WorkCenterStatusEnum.Operational,
|
||||||
criticality: CriticalityLevelEnum.High,
|
criticality: CriticalityLevelEnum.High,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC007",
|
id: 'SPEC007',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Erişim Mesafesi",
|
specificationName: 'Erişim Mesafesi',
|
||||||
specificationValue: "2033",
|
specificationValue: '2033',
|
||||||
unit: "mm",
|
unit: 'mm',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC008",
|
id: 'SPEC008',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Taşıma Kapasitesi",
|
specificationName: 'Taşıma Kapasitesi',
|
||||||
specificationValue: "60",
|
specificationValue: '60',
|
||||||
unit: "kg",
|
unit: 'kg',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -268,44 +270,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-01-15"),
|
creationTime: new Date('2023-01-15'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '4',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '4')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "7",
|
id: '7',
|
||||||
code: "WEID-001",
|
code: 'WEID-001',
|
||||||
name: "Sarma Makinesi",
|
name: 'Sarma Makinesi',
|
||||||
description: "Otomatik robot kaynak sistemi",
|
description: 'Otomatik robot kaynak sistemi',
|
||||||
workCenterId: "4",
|
workCenterId: '4',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||||
manufacturer: "KUKA",
|
manufacturer: 'KUKA',
|
||||||
model: "KR 60-3",
|
model: 'KR 60-3',
|
||||||
serialNumber: "KU556677889",
|
serialNumber: 'KU556677889',
|
||||||
installationDate: new Date("2023-01-15"),
|
installationDate: new Date('2023-01-15'),
|
||||||
warrantyExpiry: new Date("2026-01-15"),
|
warrantyExpiry: new Date('2026-01-15'),
|
||||||
location: "Kaynak Atölyesi",
|
location: 'Kaynak Atölyesi',
|
||||||
departmentId: "4",
|
departmentId: '4',
|
||||||
status: WorkCenterStatusEnum.Operational,
|
status: WorkCenterStatusEnum.Operational,
|
||||||
criticality: CriticalityLevelEnum.High,
|
criticality: CriticalityLevelEnum.High,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC007",
|
id: 'SPEC007',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Erişim Mesafesi",
|
specificationName: 'Erişim Mesafesi',
|
||||||
specificationValue: "2033",
|
specificationValue: '2033',
|
||||||
unit: "mm",
|
unit: 'mm',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC008",
|
id: 'SPEC008',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Taşıma Kapasitesi",
|
specificationName: 'Taşıma Kapasitesi',
|
||||||
specificationValue: "60",
|
specificationValue: '60',
|
||||||
unit: "kg",
|
unit: 'kg',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -313,44 +316,45 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-01-15"),
|
creationTime: new Date('2023-01-15'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '1',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "8",
|
id: '8',
|
||||||
code: "KEL-001",
|
code: 'KEL-001',
|
||||||
name: "Robot Kaynak Makinesi",
|
name: 'Robot Kaynak Makinesi',
|
||||||
description: "Otomatik robot kaynak sistemi",
|
description: 'Otomatik robot kaynak sistemi',
|
||||||
workCenterId: "4",
|
workCenterId: '4',
|
||||||
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === "4")!,
|
workCenterType: mockWorkCenterTypes.find((wct) => wct.code === '4')!,
|
||||||
manufacturer: "KUKA",
|
manufacturer: 'KUKA',
|
||||||
model: "KR 60-3",
|
model: 'KR 60-3',
|
||||||
serialNumber: "KU556677889",
|
serialNumber: 'KU556677889',
|
||||||
installationDate: new Date("2023-01-15"),
|
installationDate: new Date('2023-01-15'),
|
||||||
warrantyExpiry: new Date("2026-01-15"),
|
warrantyExpiry: new Date('2026-01-15'),
|
||||||
location: "Kaynak Atölyesi",
|
location: 'Kaynak Atölyesi',
|
||||||
departmentId: "4",
|
departmentId: '4',
|
||||||
status: WorkCenterStatusEnum.Operational,
|
status: WorkCenterStatusEnum.Operational,
|
||||||
criticality: CriticalityLevelEnum.High,
|
criticality: CriticalityLevelEnum.High,
|
||||||
specifications: [
|
specifications: [
|
||||||
{
|
{
|
||||||
id: "SPEC007",
|
id: 'SPEC007',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Erişim Mesafesi",
|
specificationName: 'Erişim Mesafesi',
|
||||||
specificationValue: "2033",
|
specificationValue: '2033',
|
||||||
unit: "mm",
|
unit: 'mm',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "SPEC008",
|
id: 'SPEC008',
|
||||||
workCenterId: "EQP004",
|
workCenterId: 'EQP004',
|
||||||
specificationName: "Taşıma Kapasitesi",
|
specificationName: 'Taşıma Kapasitesi',
|
||||||
specificationValue: "60",
|
specificationValue: '60',
|
||||||
unit: "kg",
|
unit: 'kg',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -358,11 +362,12 @@ export const mockWorkCenters: PmWorkCenter[] = [
|
||||||
workOrders: [],
|
workOrders: [],
|
||||||
downTimeHistory: [],
|
downTimeHistory: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date("2023-01-15"),
|
creationTime: new Date('2023-01-15'),
|
||||||
lastModificationTime: new Date("2024-01-20"),
|
lastModificationTime: new Date('2024-01-20'),
|
||||||
costPerHour: 85,
|
costPerHour: 85,
|
||||||
setupTime: 20,
|
setupTime: 20,
|
||||||
machineType: "CNC",
|
machineTypeId: '1',
|
||||||
|
machineType: mockWorkCenterMachineTypes.find((mt) => mt.id === '1')!,
|
||||||
capacity: 8,
|
capacity: 8,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export interface BusinessParty {
|
||||||
partyType: PartyType
|
partyType: PartyType
|
||||||
primaryContact?: Contact
|
primaryContact?: Contact
|
||||||
contacts?: Contact[]
|
contacts?: Contact[]
|
||||||
industry?: string
|
industry?: BusinessPartyIndustryEnum
|
||||||
email?: string
|
email?: string
|
||||||
phone?: string
|
phone?: string
|
||||||
website?: string
|
website?: string
|
||||||
|
|
@ -77,6 +77,21 @@ export interface BusinessParty {
|
||||||
bankAccounts?: BankAccount[]
|
bankAccounts?: BankAccount[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum BusinessPartyIndustryEnum {
|
||||||
|
// İş Ortağı Endüstrisi
|
||||||
|
Technology = 'TECHNOLOGY', // Teknoloji
|
||||||
|
Healthcare = 'HEALTHCARE', // Sağlık
|
||||||
|
Finance = 'FINANCE', // Finans
|
||||||
|
Retail = 'RETAIL', // Perakende
|
||||||
|
Manufacturing = 'MANUFACTURING', // Üretim
|
||||||
|
Education = 'EDUCATION', // Eğitim
|
||||||
|
Construction = 'CONSTRUCTION', // İnşaat
|
||||||
|
Hospitality = 'HOSPITALITY', // Konaklama
|
||||||
|
Transportation = 'TRANSPORTATION', // Ulaşım
|
||||||
|
RealEstate = 'REAL_ESTATE', // Emlak
|
||||||
|
Other = 'OTHER', // Diğer
|
||||||
|
}
|
||||||
|
|
||||||
export enum BusinessPartyStatusEnum {
|
export enum BusinessPartyStatusEnum {
|
||||||
// İş Ortağı Durumu
|
// İş Ortağı Durumu
|
||||||
Prospect = 'PROSPECT', // Potansiyel
|
Prospect = 'PROSPECT', // Potansiyel
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ export interface FiCheck {
|
||||||
amount: number
|
amount: number
|
||||||
currency: string
|
currency: string
|
||||||
status: CheckStatusEnum
|
status: CheckStatusEnum
|
||||||
type: CheckTypeEnum
|
type: TypeEnum
|
||||||
bankingDate?: Date
|
bankingDate?: Date
|
||||||
collectionDate?: Date
|
collectionDate?: Date
|
||||||
endorsedTo?: string
|
endorsedTo?: string
|
||||||
|
|
@ -227,7 +227,7 @@ export interface PromissoryNote {
|
||||||
amount: number
|
amount: number
|
||||||
currency: string
|
currency: string
|
||||||
status: NoteStatusEnum
|
status: NoteStatusEnum
|
||||||
type: NoteTypeEnum // Received or Issued
|
type: TypeEnum // Received or Issued
|
||||||
collectionDate?: Date
|
collectionDate?: Date
|
||||||
endorsedTo?: string
|
endorsedTo?: string
|
||||||
location?: string
|
location?: string
|
||||||
|
|
@ -321,7 +321,7 @@ export enum CheckStatusEnum {
|
||||||
Cancelled = 'CANCELLED', // İPTAL EDİLDİ
|
Cancelled = 'CANCELLED', // İPTAL EDİLDİ
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CheckTypeEnum {
|
export enum TypeEnum {
|
||||||
Received = 'RECEIVED', // ALINAN
|
Received = 'RECEIVED', // ALINAN
|
||||||
Issued = 'ISSUED', // VERİLEN
|
Issued = 'ISSUED', // VERİLEN
|
||||||
}
|
}
|
||||||
|
|
@ -334,11 +334,6 @@ export enum NoteStatusEnum {
|
||||||
Cancelled = 'CANCELLED', // İPTAL EDİLDİ
|
Cancelled = 'CANCELLED', // İPTAL EDİLDİ
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NoteTypeEnum {
|
|
||||||
Received = 'RECEIVED', // Alınan
|
|
||||||
Issued = 'ISSUED', // Verilen
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum WaybillTypeEnum {
|
export enum WaybillTypeEnum {
|
||||||
Outgoing = 'outgoing', // Çıkış İrsaliyesi
|
Outgoing = 'outgoing', // Çıkış İrsaliyesi
|
||||||
Incoming = 'incoming', // Giriş İrsaliyesi
|
Incoming = 'incoming', // Giriş İrsaliyesi
|
||||||
|
|
|
||||||
|
|
@ -758,3 +758,20 @@ export enum QuestionTypeEnum {
|
||||||
YesNo = 'YES_NO', // Evet/Hayır
|
YesNo = 'YES_NO', // Evet/Hayır
|
||||||
Scale = 'SCALE', // Ölçek (1-10 gibi)
|
Scale = 'SCALE', // Ölçek (1-10 gibi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getQuestionTypeText = (type: QuestionTypeEnum) => {
|
||||||
|
switch (type) {
|
||||||
|
case QuestionTypeEnum.Rating:
|
||||||
|
return 'Puanlama'
|
||||||
|
case QuestionTypeEnum.MultipleChoice:
|
||||||
|
return 'Çoktan Seçmeli'
|
||||||
|
case QuestionTypeEnum.Text:
|
||||||
|
return 'Metin'
|
||||||
|
case QuestionTypeEnum.YesNo:
|
||||||
|
return 'Evet/Hayır'
|
||||||
|
case QuestionTypeEnum.Scale:
|
||||||
|
return 'Ölçek'
|
||||||
|
default:
|
||||||
|
return 'Bilinmeyen'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -559,9 +559,11 @@ export enum OrderStatusEnum {
|
||||||
|
|
||||||
export enum SupplierTypeEnum {
|
export enum SupplierTypeEnum {
|
||||||
// Tedarikçi Türü
|
// Tedarikçi Türü
|
||||||
Material = 'MATERIAL', // Malzeme
|
Manufacturer = 'MANUFACTURER', // Üretici
|
||||||
Service = 'SERVICE', // Hizmet
|
Distributor = 'DISTRIBUTOR', // Distribütör
|
||||||
Both = 'BOTH', // Her ikisi
|
Wholesaler = 'WHOLESALER', // Toptancı
|
||||||
|
ServiceProvider = 'SERVICE_PROVIDER', // Hizmet Sağlayıcı
|
||||||
|
Other = 'OTHER', // Diğer
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RequisitionStatusEnum {
|
export enum RequisitionStatusEnum {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@ export interface PmWorkCenter {
|
||||||
capacity: number
|
capacity: number
|
||||||
costPerHour: number
|
costPerHour: number
|
||||||
setupTime: number
|
setupTime: number
|
||||||
machineType: string
|
machineTypeId: string
|
||||||
|
machineType?: PmMachineType
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
creationTime: Date
|
creationTime: Date
|
||||||
lastModificationTime: Date
|
lastModificationTime: Date
|
||||||
|
|
@ -45,6 +46,14 @@ export interface PmWorkCenterType {
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PmMachineType {
|
||||||
|
// Makina Türü
|
||||||
|
id: string
|
||||||
|
code: string
|
||||||
|
name: string
|
||||||
|
isActive: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface PmWorkCenterSpecification {
|
export interface PmWorkCenterSpecification {
|
||||||
// İş Merkezi / Ekipman Özelliği
|
// İş Merkezi / Ekipman Özelliği
|
||||||
id: string
|
id: string
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export interface PsProjectPhase {
|
||||||
assignedTeams: string[]
|
assignedTeams: string[]
|
||||||
deliverables: string[]
|
deliverables: string[]
|
||||||
risks: string[]
|
risks: string[]
|
||||||
category: string
|
category: PhaseCategoryEnum
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PsProjectTask {
|
export interface PsProjectTask {
|
||||||
|
|
@ -172,7 +172,7 @@ export interface PsProjectCostTracking {
|
||||||
plannedDuration: number // days
|
plannedDuration: number // days
|
||||||
actualDuration?: number // days
|
actualDuration?: number // days
|
||||||
progress: number // percentage
|
progress: number // percentage
|
||||||
status: 'ON_TRACK' | 'AT_RISK' | 'DELAYED' | 'COMPLETED'
|
status: ProjectCostTrackingStatus
|
||||||
currency: string
|
currency: string
|
||||||
lastUpdated: Date
|
lastUpdated: Date
|
||||||
}
|
}
|
||||||
|
|
@ -255,6 +255,15 @@ export enum ProjectStatusEnum {
|
||||||
Cancelled = 'CANCELLED', // İptal Edildi
|
Cancelled = 'CANCELLED', // İptal Edildi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PhaseCategoryEnum {
|
||||||
|
// Category of Phase
|
||||||
|
Planning = 'PLANNING', // Planlama
|
||||||
|
Development = 'EXECUTION', // Yürütme
|
||||||
|
Testing = 'MONITORING', // İzleme
|
||||||
|
Deployment = 'CLOSURE', // Kapanış
|
||||||
|
Design = 'OTHER', // Diğer
|
||||||
|
}
|
||||||
|
|
||||||
export enum PhaseStatusEnum {
|
export enum PhaseStatusEnum {
|
||||||
// Faz Durumu
|
// Faz Durumu
|
||||||
NotStarted = 'NOT_STARTED', // Başlanmadı
|
NotStarted = 'NOT_STARTED', // Başlanmadı
|
||||||
|
|
@ -354,3 +363,11 @@ export enum PsDocumentTypeEnum {
|
||||||
Manual = 'MANUAL', // Kılavuz
|
Manual = 'MANUAL', // Kılavuz
|
||||||
Other = 'OTHER', // Diğer
|
Other = 'OTHER', // Diğer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjectCostTrackingStatus {
|
||||||
|
// Proje Maliyet Takibi Durumu
|
||||||
|
OnTrack = 'ON_TRACK', // Planında
|
||||||
|
AtRisk = 'AT_RISK', // Riskte
|
||||||
|
Delayed = 'DELAYED', // Gecikmiş
|
||||||
|
Completed = 'COMPLETED', // Tamamlandı
|
||||||
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,159 +1,151 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaSave, FaTimes, FaBuilding } from "react-icons/fa";
|
import { FaSave, FaTimes, FaBuilding } from 'react-icons/fa'
|
||||||
import { BankAccountTypeEnum } from "../../../types/fi";
|
import { BankAccountTypeEnum } from '../../../types/fi'
|
||||||
import { BankAccount } from "../../../types/common";
|
import { BankAccount } from '../../../types/common'
|
||||||
|
import { getBankAccountTypeText } from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
interface BankAccountFormProps {
|
interface BankAccountFormProps {
|
||||||
account?: BankAccount;
|
account?: BankAccount
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (account: Partial<BankAccount>) => void;
|
onSave: (account: Partial<BankAccount>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
const BankAccountForm: React.FC<BankAccountFormProps> = ({ account, isOpen, onClose, onSave }) => {
|
||||||
account,
|
|
||||||
isOpen,
|
|
||||||
onClose,
|
|
||||||
onSave,
|
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState<Partial<BankAccount>>({
|
const [formData, setFormData] = useState<Partial<BankAccount>>({
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
bankName: "",
|
bankName: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountNumber: "",
|
accountNumber: '',
|
||||||
iban: "",
|
iban: '',
|
||||||
accountType: BankAccountTypeEnum.Current,
|
accountType: BankAccountTypeEnum.Current,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
balance: 0,
|
balance: 0,
|
||||||
overdraftLimit: 0,
|
overdraftLimit: 0,
|
||||||
dailyTransferLimit: 0,
|
dailyTransferLimit: 0,
|
||||||
contactPerson: "",
|
contactPerson: '',
|
||||||
phone: "",
|
phone: '',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (account) {
|
if (account) {
|
||||||
setFormData(account);
|
setFormData(account)
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
bankName: "",
|
bankName: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountNumber: "",
|
accountNumber: '',
|
||||||
iban: "",
|
iban: '',
|
||||||
accountType: BankAccountTypeEnum.Current,
|
accountType: BankAccountTypeEnum.Current,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
balance: 0,
|
balance: 0,
|
||||||
overdraftLimit: 0,
|
overdraftLimit: 0,
|
||||||
dailyTransferLimit: 0,
|
dailyTransferLimit: 0,
|
||||||
contactPerson: "",
|
contactPerson: '',
|
||||||
phone: "",
|
phone: '',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setErrors({});
|
setErrors({})
|
||||||
}, [account, isOpen]);
|
}, [account, isOpen])
|
||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const newErrors: Record<string, string> = {};
|
const newErrors: Record<string, string> = {}
|
||||||
|
|
||||||
if (!formData.accountCode?.trim()) {
|
if (!formData.accountCode?.trim()) {
|
||||||
newErrors.accountCode = "Hesap kodu gereklidir";
|
newErrors.accountCode = 'Hesap kodu gereklidir'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.bankName?.trim()) {
|
if (!formData.bankName?.trim()) {
|
||||||
newErrors.bankName = "Banka adı gereklidir";
|
newErrors.bankName = 'Banka adı gereklidir'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.branchName?.trim()) {
|
if (!formData.branchName?.trim()) {
|
||||||
newErrors.branchName = "Şube adı gereklidir";
|
newErrors.branchName = 'Şube adı gereklidir'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.accountNumber?.trim()) {
|
if (!formData.accountNumber?.trim()) {
|
||||||
newErrors.accountNumber = "Hesap numarası gereklidir";
|
newErrors.accountNumber = 'Hesap numarası gereklidir'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.iban?.trim()) {
|
if (!formData.iban?.trim()) {
|
||||||
newErrors.iban = "IBAN gereklidir";
|
newErrors.iban = 'IBAN gereklidir'
|
||||||
} else if (formData.iban.length < 26) {
|
} else if (formData.iban.length < 26) {
|
||||||
newErrors.iban = "IBAN geçerli formatta olmalıdır";
|
newErrors.iban = 'IBAN geçerli formatta olmalıdır'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.currency?.trim()) {
|
if (!formData.currency?.trim()) {
|
||||||
newErrors.currency = "Para birimi gereklidir";
|
newErrors.currency = 'Para birimi gereklidir'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (formData.dailyTransferLimit !== undefined && formData.dailyTransferLimit < 0) {
|
||||||
formData.dailyTransferLimit !== undefined &&
|
newErrors.dailyTransferLimit = 'Günlük transfer limiti negatif olamaz'
|
||||||
formData.dailyTransferLimit < 0
|
|
||||||
) {
|
|
||||||
newErrors.dailyTransferLimit = "Günlük transfer limiti negatif olamaz";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.overdraftLimit !== undefined && formData.overdraftLimit < 0) {
|
if (formData.overdraftLimit !== undefined && formData.overdraftLimit < 0) {
|
||||||
newErrors.overdraftLimit = "Kredi limiti negatif olamaz";
|
newErrors.overdraftLimit = 'Kredi limiti negatif olamaz'
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors)
|
||||||
return Object.keys(newErrors).length === 0;
|
return Object.keys(newErrors).length === 0
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
onSave(formData);
|
onSave(formData)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
e: React.ChangeEvent<
|
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
||||||
>
|
|
||||||
) => {
|
) => {
|
||||||
const { name, value, type } = e.target;
|
const { name, value, type } = e.target
|
||||||
const parsedValue = type === "number" ? parseFloat(value) || 0 : value;
|
const parsedValue = type === 'number' ? parseFloat(value) || 0 : value
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: parsedValue,
|
[name]: parsedValue,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// Clear error when user starts typing
|
// Clear error when user starts typing
|
||||||
if (errors[name]) {
|
if (errors[name]) {
|
||||||
setErrors((prev) => ({
|
setErrors((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: "",
|
[name]: '',
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const { name, checked } = e.target;
|
const { name, checked } = e.target
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: checked,
|
[name]: checked,
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleIbanChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleIbanChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
let value = e.target.value;
|
let value = e.target.value
|
||||||
|
|
||||||
// Sadece harf ve rakam kalsın
|
// Sadece harf ve rakam kalsın
|
||||||
value = value.replace(/[^A-Za-z0-9]/g, "");
|
value = value.replace(/[^A-Za-z0-9]/g, '')
|
||||||
|
|
||||||
// 4 karakterde bir boşluk ekle
|
// 4 karakterde bir boşluk ekle
|
||||||
value = value.replace(/(.{4})/g, "$1 ").trim();
|
value = value.replace(/(.{4})/g, '$1 ').trim()
|
||||||
|
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
iban: value,
|
iban: value,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
|
@ -162,7 +154,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<FaBuilding className="w-5 h-5 text-blue-600" />
|
<FaBuilding className="w-5 h-5 text-blue-600" />
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{account ? "Banka Hesabını Düzenle" : "Yeni Banka Hesabı"}
|
{account ? 'Banka Hesabını Düzenle' : 'Yeni Banka Hesabı'}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -182,80 +174,67 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Kodu *</label>
|
||||||
Hesap Kodu *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="accountCode"
|
name="accountCode"
|
||||||
value={formData.accountCode || ""}
|
value={formData.accountCode || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.accountCode ? "border-red-500" : "border-gray-300"
|
errors.accountCode ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Örn: BANKA001"
|
placeholder="Örn: BANKA001"
|
||||||
/>
|
/>
|
||||||
{errors.accountCode && (
|
{errors.accountCode && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.accountCode}</p>
|
||||||
{errors.accountCode}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
|
||||||
Banka Adı *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="bankName"
|
name="bankName"
|
||||||
value={formData.bankName || ""}
|
value={formData.bankName || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.bankName ? "border-red-500" : "border-gray-300"
|
errors.bankName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Örn: İş Bankası"
|
placeholder="Örn: İş Bankası"
|
||||||
/>
|
/>
|
||||||
{errors.bankName && (
|
{errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.bankName}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı *</label>
|
||||||
Şube Adı *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="branchName"
|
name="branchName"
|
||||||
value={formData.branchName || ""}
|
value={formData.branchName || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.branchName ? "border-red-500" : "border-gray-300"
|
errors.branchName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Örn: Levent Şubesi"
|
placeholder="Örn: Levent Şubesi"
|
||||||
/>
|
/>
|
||||||
{errors.branchName && (
|
{errors.branchName && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.branchName}</p>
|
||||||
{errors.branchName}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Türü</label>
|
||||||
Hesap Türü
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="accountType"
|
name="accountType"
|
||||||
value={formData.accountType || BankAccountTypeEnum.Current}
|
value={formData.accountType || BankAccountTypeEnum.Current}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={BankAccountTypeEnum.Current}>Vadesiz</option>
|
{Object.values(BankAccountTypeEnum).map((type) => (
|
||||||
<option value={BankAccountTypeEnum.Deposit}>Vadeli</option>
|
<option key={type} value={type}>
|
||||||
<option value={BankAccountTypeEnum.Credit}>Kredi</option>
|
{getBankAccountTypeText(type)}
|
||||||
<option value={BankAccountTypeEnum.Foreign}>Döviz</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -265,20 +244,19 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
name="currency"
|
name="currency"
|
||||||
value={formData.currency || "TRY"}
|
value={formData.currency || 'TRY'}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.currency ? "border-red-500" : "border-gray-300"
|
errors.currency ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY - Türk Lirası</option>
|
{mockCurrencies.map((cur) => (
|
||||||
<option value="USD">USD - Amerikan Doları</option>
|
<option key={cur.value} value={cur.value}>
|
||||||
<option value="EUR">EUR - Euro</option>
|
{cur.value} - {cur.label}
|
||||||
<option value="GBP">GBP - İngiliz Sterlini</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.currency && (
|
{errors.currency && <p className="text-red-500 text-xs mt-1">{errors.currency}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.currency}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -295,38 +273,32 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="accountNumber"
|
name="accountNumber"
|
||||||
value={formData.accountNumber || ""}
|
value={formData.accountNumber || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.accountNumber ? "border-red-500" : "border-gray-300"
|
errors.accountNumber ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="1234567890"
|
placeholder="1234567890"
|
||||||
/>
|
/>
|
||||||
{errors.accountNumber && (
|
{errors.accountNumber && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.accountNumber}</p>
|
||||||
{errors.accountNumber}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">IBAN *</label>
|
||||||
IBAN *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="iban"
|
name="iban"
|
||||||
value={formData.iban || ""}
|
value={formData.iban || ''}
|
||||||
onChange={handleIbanChange}
|
onChange={handleIbanChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono ${
|
||||||
errors.iban ? "border-red-500" : "border-gray-300"
|
errors.iban ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="TR12 0006 4000 0011 2345 6789 01"
|
placeholder="TR12 0006 4000 0011 2345 6789 01"
|
||||||
maxLength={34}
|
maxLength={34}
|
||||||
/>
|
/>
|
||||||
{errors.iban && (
|
{errors.iban && <p className="text-red-500 text-xs mt-1">{errors.iban}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.iban}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -344,24 +316,20 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Kredi Limiti</label>
|
||||||
Kredi Limiti
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
name="overdraftLimit"
|
name="overdraftLimit"
|
||||||
value={formData.overdraftLimit || 0}
|
value={formData.overdraftLimit || 0}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.overdraftLimit ? "border-red-500" : "border-gray-300"
|
errors.overdraftLimit ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
step="0.01"
|
step="0.01"
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
{errors.overdraftLimit && (
|
{errors.overdraftLimit && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.overdraftLimit}</p>
|
||||||
{errors.overdraftLimit}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -375,17 +343,13 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
value={formData.dailyTransferLimit || 0}
|
value={formData.dailyTransferLimit || 0}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.dailyTransferLimit
|
errors.dailyTransferLimit ? 'border-red-500' : 'border-gray-300'
|
||||||
? "border-red-500"
|
|
||||||
: "border-gray-300"
|
|
||||||
}`}
|
}`}
|
||||||
step="0.01"
|
step="0.01"
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
{errors.dailyTransferLimit && (
|
{errors.dailyTransferLimit && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.dailyTransferLimit}</p>
|
||||||
{errors.dailyTransferLimit}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -404,7 +368,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="contactPerson"
|
name="contactPerson"
|
||||||
value={formData.contactPerson || ""}
|
value={formData.contactPerson || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Ad Soyad"
|
placeholder="Ad Soyad"
|
||||||
|
|
@ -412,13 +376,11 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
|
||||||
Telefon
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
name="phone"
|
name="phone"
|
||||||
value={formData.phone || ""}
|
value={formData.phone || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="+90 212 555 1234"
|
placeholder="+90 212 555 1234"
|
||||||
|
|
@ -434,9 +396,7 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
onChange={handleCheckboxChange}
|
onChange={handleCheckboxChange}
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<label className="ml-2 block text-sm text-gray-700">
|
<label className="ml-2 block text-sm text-gray-700">Hesap aktif</label>
|
||||||
Hesap aktif
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -455,13 +415,13 @@ const BankAccountForm: React.FC<BankAccountFormProps> = ({
|
||||||
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{account ? "Güncelle" : "Kaydet"}
|
{account ? 'Güncelle' : 'Kaydet'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default BankAccountForm;
|
export default BankAccountForm
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaCreditCard, FaSave, FaTimes } from "react-icons/fa";
|
import { FaCreditCard, FaSave, FaTimes } from 'react-icons/fa'
|
||||||
import {
|
import { FiCheck, TypeEnum, CheckStatusEnum, FiCurrentAccount } from '../../../types/fi'
|
||||||
FiCheck,
|
import { getCheckStatusText, getTypeText } from '@/utils/erp'
|
||||||
CheckTypeEnum,
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
CheckStatusEnum,
|
|
||||||
FiCurrentAccount,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
|
|
||||||
interface CheckFormProps {
|
interface CheckFormProps {
|
||||||
check?: FiCheck;
|
check?: FiCheck
|
||||||
currentAccounts: FiCurrentAccount[];
|
currentAccounts: FiCurrentAccount[]
|
||||||
onSave: (
|
onSave: (check: Omit<FiCheck, 'id' | 'creationTime' | 'lastModificationTime'>) => void
|
||||||
check: Omit<FiCheck, "id" | "creationTime" | "lastModificationTime">
|
onCancel: () => void
|
||||||
) => void;
|
isOpen: boolean
|
||||||
onCancel: () => void;
|
|
||||||
isOpen: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckForm: React.FC<CheckFormProps> = ({
|
const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
|
|
@ -25,23 +20,23 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
checkNumber: "",
|
checkNumber: '',
|
||||||
bankName: "",
|
bankName: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountNumber: "",
|
accountNumber: '',
|
||||||
drawerName: "",
|
drawerName: '',
|
||||||
payeeName: "",
|
payeeName: '',
|
||||||
currentAccountId: "",
|
currentAccountId: '',
|
||||||
issueDate: new Date().toISOString().split("T")[0],
|
issueDate: new Date().toISOString().split('T')[0],
|
||||||
dueDate: new Date().toISOString().split("T")[0],
|
dueDate: new Date().toISOString().split('T')[0],
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: CheckStatusEnum.InHand,
|
status: CheckStatusEnum.InHand,
|
||||||
type: CheckTypeEnum.Received,
|
type: TypeEnum.Received,
|
||||||
notes: "",
|
notes: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (check) {
|
if (check) {
|
||||||
|
|
@ -52,64 +47,64 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
accountNumber: check.accountNumber,
|
accountNumber: check.accountNumber,
|
||||||
drawerName: check.drawerName,
|
drawerName: check.drawerName,
|
||||||
payeeName: check.payeeName,
|
payeeName: check.payeeName,
|
||||||
currentAccountId: check.currentAccountId || "",
|
currentAccountId: check.currentAccountId || '',
|
||||||
issueDate: new Date(check.issueDate).toISOString().split("T")[0],
|
issueDate: new Date(check.issueDate).toISOString().split('T')[0],
|
||||||
dueDate: new Date(check.dueDate).toISOString().split("T")[0],
|
dueDate: new Date(check.dueDate).toISOString().split('T')[0],
|
||||||
amount: check.amount,
|
amount: check.amount,
|
||||||
currency: check.currency,
|
currency: check.currency,
|
||||||
status: check.status,
|
status: check.status,
|
||||||
type: check.type,
|
type: check.type,
|
||||||
notes: check.notes || "",
|
notes: check.notes || '',
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
checkNumber: "",
|
checkNumber: '',
|
||||||
bankName: "",
|
bankName: '',
|
||||||
branchName: "",
|
branchName: '',
|
||||||
accountNumber: "",
|
accountNumber: '',
|
||||||
drawerName: "",
|
drawerName: '',
|
||||||
payeeName: "",
|
payeeName: '',
|
||||||
currentAccountId: "",
|
currentAccountId: '',
|
||||||
issueDate: new Date().toISOString().split("T")[0],
|
issueDate: new Date().toISOString().split('T')[0],
|
||||||
dueDate: new Date().toISOString().split("T")[0],
|
dueDate: new Date().toISOString().split('T')[0],
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: CheckStatusEnum.InHand,
|
status: CheckStatusEnum.InHand,
|
||||||
type: CheckTypeEnum.Received,
|
type: TypeEnum.Received,
|
||||||
notes: "",
|
notes: '',
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setErrors({});
|
setErrors({})
|
||||||
}, [check, isOpen]);
|
}, [check, isOpen])
|
||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const newErrors: Record<string, string> = {};
|
const newErrors: Record<string, string> = {}
|
||||||
|
|
||||||
if (!formData.checkNumber.trim()) {
|
if (!formData.checkNumber.trim()) {
|
||||||
newErrors.checkNumber = "Çek numarası gereklidir";
|
newErrors.checkNumber = 'Çek numarası gereklidir'
|
||||||
}
|
}
|
||||||
if (!formData.bankName.trim()) {
|
if (!formData.bankName.trim()) {
|
||||||
newErrors.bankName = "Banka adı gereklidir";
|
newErrors.bankName = 'Banka adı gereklidir'
|
||||||
}
|
}
|
||||||
if (!formData.drawerName.trim()) {
|
if (!formData.drawerName.trim()) {
|
||||||
newErrors.drawerName = "Keşideci adı gereklidir";
|
newErrors.drawerName = 'Keşideci adı gereklidir'
|
||||||
}
|
}
|
||||||
if (!formData.payeeName.trim()) {
|
if (!formData.payeeName.trim()) {
|
||||||
newErrors.payeeName = "Lehtar adı gereklidir";
|
newErrors.payeeName = 'Lehtar adı gereklidir'
|
||||||
}
|
}
|
||||||
if (formData.amount <= 0) {
|
if (formData.amount <= 0) {
|
||||||
newErrors.amount = "Tutar 0'dan büyük olmalıdır";
|
newErrors.amount = "Tutar 0'dan büyük olmalıdır"
|
||||||
}
|
}
|
||||||
if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
|
if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
|
||||||
newErrors.dueDate = "Vade tarihi düzenleme tarihinden sonra olmalıdır";
|
newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors)
|
||||||
return Object.keys(newErrors).length === 0;
|
return Object.keys(newErrors).length === 0
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
const checkData = {
|
const checkData = {
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -118,22 +113,22 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
currentAccount: formData.currentAccountId
|
currentAccount: formData.currentAccountId
|
||||||
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
|
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
}
|
||||||
onSave(checkData);
|
onSave(checkData)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
field: string,
|
field: string,
|
||||||
value: string | number | CheckTypeEnum | CheckStatusEnum
|
value: string | number | TypeEnum | CheckStatusEnum,
|
||||||
) => {
|
) => {
|
||||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
setFormData((prev) => ({ ...prev, [field]: value }))
|
||||||
if (errors[field]) {
|
if (errors[field]) {
|
||||||
setErrors((prev) => ({ ...prev, [field]: "" }));
|
setErrors((prev) => ({ ...prev, [field]: '' }))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
|
@ -142,13 +137,10 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<FaCreditCard className="w-5 h-5 text-blue-600" />
|
<FaCreditCard className="w-5 h-5 text-blue-600" />
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{check ? "Çek Düzenle" : "Yeni Çek"}
|
{check ? 'Çek Düzenle' : 'Yeni Çek'}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
|
||||||
onClick={onCancel}
|
|
||||||
className="p-2 hover:bg-gray-100 rounded-md"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -157,102 +149,76 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
{/* Çek Bilgileri */}
|
{/* Çek Bilgileri */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Çek Numarası *</label>
|
||||||
Çek Numarası *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.checkNumber}
|
value={formData.checkNumber}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('checkNumber', e.target.value)}
|
||||||
handleInputChange("checkNumber", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.checkNumber ? "border-red-500" : "border-gray-300"
|
errors.checkNumber ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Çek numarasını giriniz"
|
placeholder="Çek numarasını giriniz"
|
||||||
/>
|
/>
|
||||||
{errors.checkNumber && (
|
{errors.checkNumber && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.checkNumber}</p>
|
||||||
{errors.checkNumber}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
|
||||||
Tür *
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.type}
|
value={formData.type}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
|
||||||
handleInputChange("type", e.target.value as CheckTypeEnum)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CheckTypeEnum.Received}>Alınan Çek</option>
|
{Object.values(TypeEnum).map((type) => (
|
||||||
<option value={CheckTypeEnum.Issued}>Verilen Çek</option>
|
<option key={type} value={type}>
|
||||||
|
{getTypeText(type)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||||
Durum
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.status}
|
value={formData.status}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('status', e.target.value as CheckStatusEnum)}
|
||||||
handleInputChange("status", e.target.value as CheckStatusEnum)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CheckStatusEnum.InHand}>Elde</option>
|
{Object.values(CheckStatusEnum).map((status) => (
|
||||||
<option value={CheckStatusEnum.Deposited}>
|
<option key={status} value={status}>
|
||||||
Bankaya Verildi
|
{getCheckStatusText(status)}
|
||||||
</option>
|
</option>
|
||||||
<option value={CheckStatusEnum.Collected}>Tahsil Edildi</option>
|
))}
|
||||||
<option value={CheckStatusEnum.Bounced}>Karşılıksız</option>
|
|
||||||
<option value={CheckStatusEnum.Endorsed}>Ciro Edildi</option>
|
|
||||||
<option value={CheckStatusEnum.Cancelled}>İptal</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Banka Bilgileri */}
|
{/* Banka Bilgileri */}
|
||||||
<div className="bg-gray-50 p-3 rounded-lg">
|
<div className="bg-gray-50 p-3 rounded-lg">
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-3">
|
<h3 className="text-base font-medium text-gray-900 mb-3">Banka Bilgileri</h3>
|
||||||
Banka Bilgileri
|
|
||||||
</h3>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
|
||||||
Banka Adı *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.bankName}
|
value={formData.bankName}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('bankName', e.target.value)}
|
||||||
handleInputChange("bankName", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.bankName ? "border-red-500" : "border-gray-300"
|
errors.bankName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Banka adını giriniz"
|
placeholder="Banka adını giriniz"
|
||||||
/>
|
/>
|
||||||
{errors.bankName && (
|
{errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.bankName}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı</label>
|
||||||
Şube Adı
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.branchName}
|
value={formData.branchName}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('branchName', e.target.value)}
|
||||||
handleInputChange("branchName", e.target.value)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Şube adını giriniz"
|
placeholder="Şube adını giriniz"
|
||||||
/>
|
/>
|
||||||
|
|
@ -265,9 +231,7 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.accountNumber}
|
value={formData.accountNumber}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('accountNumber', e.target.value)}
|
||||||
handleInputChange("accountNumber", e.target.value)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Hesap numarasını giriniz"
|
placeholder="Hesap numarasını giriniz"
|
||||||
/>
|
/>
|
||||||
|
|
@ -277,63 +241,45 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
|
|
||||||
{/* Taraf Bilgileri */}
|
{/* Taraf Bilgileri */}
|
||||||
<div className="bg-gray-50 p-3 rounded-lg">
|
<div className="bg-gray-50 p-3 rounded-lg">
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-3">
|
<h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
|
||||||
Taraf Bilgileri
|
|
||||||
</h3>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
|
||||||
Keşideci *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.drawerName}
|
value={formData.drawerName}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('drawerName', e.target.value)}
|
||||||
handleInputChange("drawerName", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.drawerName ? "border-red-500" : "border-gray-300"
|
errors.drawerName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Keşideci adını giriniz"
|
placeholder="Keşideci adını giriniz"
|
||||||
/>
|
/>
|
||||||
{errors.drawerName && (
|
{errors.drawerName && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
|
||||||
{errors.drawerName}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
|
||||||
Lehtar *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.payeeName}
|
value={formData.payeeName}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('payeeName', e.target.value)}
|
||||||
handleInputChange("payeeName", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.payeeName ? "border-red-500" : "border-gray-300"
|
errors.payeeName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Lehtar adını giriniz"
|
placeholder="Lehtar adını giriniz"
|
||||||
/>
|
/>
|
||||||
{errors.payeeName && (
|
{errors.payeeName && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
|
||||||
{errors.payeeName}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
|
||||||
Cari Hesap
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currentAccountId}
|
value={formData.currentAccountId}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('currentAccountId', e.target.value)}
|
||||||
handleInputChange("currentAccountId", e.target.value)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Cari hesap seçiniz</option>
|
<option value="">Cari hesap seçiniz</option>
|
||||||
|
|
@ -350,39 +296,33 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
{/* Tutar ve Tarih Bilgileri */}
|
{/* Tutar ve Tarih Bilgileri */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
|
||||||
Tutar *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
min="0"
|
min="0"
|
||||||
value={formData.amount}
|
value={formData.amount}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('amount', parseFloat(e.target.value) || 0)}
|
||||||
handleInputChange("amount", parseFloat(e.target.value) || 0)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.amount ? "border-red-500" : "border-gray-300"
|
errors.amount ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="0.00"
|
placeholder="0.00"
|
||||||
/>
|
/>
|
||||||
{errors.amount && (
|
{errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.amount}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||||
Para Birimi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currency}
|
value={formData.currency}
|
||||||
onChange={(e) => handleInputChange("currency", e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -393,37 +333,31 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.issueDate}
|
value={formData.issueDate}
|
||||||
onChange={(e) => handleInputChange("issueDate", e.target.value)}
|
onChange={(e) => handleInputChange('issueDate', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
|
||||||
Vade Tarihi *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.dueDate}
|
value={formData.dueDate}
|
||||||
onChange={(e) => handleInputChange("dueDate", e.target.value)}
|
onChange={(e) => handleInputChange('dueDate', e.target.value)}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.dueDate ? "border-red-500" : "border-gray-300"
|
errors.dueDate ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
{errors.dueDate && (
|
{errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Notlar */}
|
{/* Notlar */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
|
||||||
Notlar
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.notes}
|
value={formData.notes}
|
||||||
onChange={(e) => handleInputChange("notes", e.target.value)}
|
onChange={(e) => handleInputChange('notes', e.target.value)}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Ek notlar..."
|
placeholder="Ek notlar..."
|
||||||
|
|
@ -444,13 +378,13 @@ const CheckForm: React.FC<CheckFormProps> = ({
|
||||||
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{check ? "Güncelle" : "Kaydet"}
|
{check ? 'Güncelle' : 'Kaydet'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CheckForm;
|
export default CheckForm
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
FaCreditCard,
|
FaCreditCard,
|
||||||
FaFileAlt,
|
FaFileAlt,
|
||||||
|
|
@ -7,113 +7,84 @@ import {
|
||||||
FaUser,
|
FaUser,
|
||||||
FaMoneyBillWave,
|
FaMoneyBillWave,
|
||||||
FaInfoCircle,
|
FaInfoCircle,
|
||||||
} from "react-icons/fa";
|
} from 'react-icons/fa'
|
||||||
import {
|
import {
|
||||||
FiCheck,
|
FiCheck,
|
||||||
PromissoryNote,
|
PromissoryNote,
|
||||||
CheckStatusEnum,
|
CheckStatusEnum,
|
||||||
NoteStatusEnum,
|
NoteStatusEnum,
|
||||||
CheckTypeEnum,
|
TypeEnum,
|
||||||
NoteTypeEnum,
|
} from '../../../types/fi'
|
||||||
} from "../../../types/fi";
|
import {
|
||||||
|
getCheckStatusColor,
|
||||||
|
getCheckStatusText,
|
||||||
|
getNoteStatusColor,
|
||||||
|
getNoteStatusText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
|
||||||
interface CheckNoteDetailsProps {
|
interface CheckNoteDetailsProps {
|
||||||
item: FiCheck | PromissoryNote;
|
item: FiCheck | PromissoryNote
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({ item, onClose, isOpen }) => {
|
||||||
item,
|
if (!isOpen) return null
|
||||||
onClose,
|
|
||||||
isOpen,
|
|
||||||
}) => {
|
|
||||||
if (!isOpen) return null;
|
|
||||||
|
|
||||||
const isCheck = "checkNumber" in item;
|
const isCheck = 'checkNumber' in item
|
||||||
const formatCurrency = (amount: number) => {
|
const formatCurrency = (amount: number) => {
|
||||||
return amount.toLocaleString("tr-TR", {
|
return amount.toLocaleString('tr-TR', {
|
||||||
style: "currency",
|
style: 'currency',
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const getStatusLabel = (status: CheckStatusEnum | NoteStatusEnum) => {
|
const getStatusLabel = (status: CheckStatusEnum | NoteStatusEnum) => {
|
||||||
if (isCheck) {
|
if (isCheck) {
|
||||||
const statusLabels = {
|
return getCheckStatusText(status as CheckStatusEnum)
|
||||||
[CheckStatusEnum.InHand]: "Elde",
|
|
||||||
[CheckStatusEnum.Deposited]: "Bankaya Verildi",
|
|
||||||
[CheckStatusEnum.Collected]: "Tahsil Edildi",
|
|
||||||
[CheckStatusEnum.Bounced]: "Karşılıksız",
|
|
||||||
[CheckStatusEnum.Endorsed]: "Ciro Edildi",
|
|
||||||
[CheckStatusEnum.Cancelled]: "İptal",
|
|
||||||
};
|
|
||||||
return statusLabels[status as CheckStatusEnum];
|
|
||||||
} else {
|
} else {
|
||||||
const statusLabels = {
|
return getNoteStatusText(status as NoteStatusEnum)
|
||||||
[NoteStatusEnum.InHand]: "Elde",
|
|
||||||
[NoteStatusEnum.Collected]: "Tahsil Edildi",
|
|
||||||
[NoteStatusEnum.Overdue]: "Vadesi Geçmiş",
|
|
||||||
[NoteStatusEnum.Endorsed]: "Ciro Edildi",
|
|
||||||
[NoteStatusEnum.Cancelled]: "İptal",
|
|
||||||
};
|
|
||||||
return statusLabels[status as NoteStatusEnum];
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const getStatusColor = (status: CheckStatusEnum | NoteStatusEnum) => {
|
const getStatusColor = (status: CheckStatusEnum | NoteStatusEnum) => {
|
||||||
if (isCheck) {
|
if (isCheck) {
|
||||||
const statusColors = {
|
return getCheckStatusColor(status as CheckStatusEnum)
|
||||||
[CheckStatusEnum.InHand]: "bg-blue-100 text-blue-800",
|
|
||||||
[CheckStatusEnum.Deposited]: "bg-yellow-100 text-yellow-800",
|
|
||||||
[CheckStatusEnum.Collected]: "bg-green-100 text-green-800",
|
|
||||||
[CheckStatusEnum.Bounced]: "bg-red-100 text-red-800",
|
|
||||||
[CheckStatusEnum.Endorsed]: "bg-purple-100 text-purple-800",
|
|
||||||
[CheckStatusEnum.Cancelled]: "bg-gray-100 text-gray-800",
|
|
||||||
};
|
|
||||||
return statusColors[status as CheckStatusEnum];
|
|
||||||
} else {
|
} else {
|
||||||
const statusColors = {
|
return getNoteStatusColor(status as NoteStatusEnum)
|
||||||
[NoteStatusEnum.InHand]: "bg-blue-100 text-blue-800",
|
|
||||||
[NoteStatusEnum.Collected]: "bg-green-100 text-green-800",
|
|
||||||
[NoteStatusEnum.Overdue]: "bg-red-100 text-red-800",
|
|
||||||
[NoteStatusEnum.Endorsed]: "bg-purple-100 text-purple-800",
|
|
||||||
[NoteStatusEnum.Cancelled]: "bg-gray-100 text-gray-800",
|
|
||||||
};
|
|
||||||
return statusColors[status as NoteStatusEnum];
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const getTypeLabel = (type: CheckTypeEnum | NoteTypeEnum) => {
|
const getTypeLabel = (type: TypeEnum) => {
|
||||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
if (type === TypeEnum.Received) {
|
||||||
return "Alınan";
|
return 'Alınan'
|
||||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
} else if (type === TypeEnum.Issued) {
|
||||||
return "Verilen";
|
return 'Verilen'
|
||||||
}
|
}
|
||||||
return "Bilinmeyen";
|
return 'Bilinmeyen'
|
||||||
};
|
}
|
||||||
|
|
||||||
const getTypeColor = (type: CheckTypeEnum | NoteTypeEnum) => {
|
const getTypeColor = (type: TypeEnum) => {
|
||||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
if (type === TypeEnum.Received) {
|
||||||
return "bg-green-100 text-green-800";
|
return 'bg-green-100 text-green-800'
|
||||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
} else if (type === TypeEnum.Issued) {
|
||||||
return "bg-orange-100 text-orange-800";
|
return 'bg-orange-100 text-orange-800'
|
||||||
}
|
}
|
||||||
return "bg-gray-100 text-gray-800";
|
return 'bg-gray-100 text-gray-800'
|
||||||
};
|
}
|
||||||
|
|
||||||
const getDaysUntilDue = (dueDate: Date) => {
|
const getDaysUntilDue = (dueDate: Date) => {
|
||||||
const today = new Date();
|
const today = new Date()
|
||||||
const due = new Date(dueDate);
|
const due = new Date(dueDate)
|
||||||
const diffTime = due.getTime() - today.getTime();
|
const diffTime = due.getTime() - today.getTime()
|
||||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||||
return diffDays;
|
return diffDays
|
||||||
};
|
}
|
||||||
|
|
||||||
const daysUntilDue = getDaysUntilDue(item.dueDate);
|
const daysUntilDue = getDaysUntilDue(item.dueDate)
|
||||||
const isOverdue = daysUntilDue < 0;
|
const isOverdue = daysUntilDue < 0
|
||||||
const isDueSoon = daysUntilDue <= 7 && daysUntilDue >= 0;
|
const isDueSoon = daysUntilDue <= 7 && daysUntilDue >= 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
|
@ -127,19 +98,14 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{isCheck ? "Çek Detayları" : "Senet Detayları"}
|
{isCheck ? 'Çek Detayları' : 'Senet Detayları'}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm text-gray-600">
|
<p className="text-sm text-gray-600">
|
||||||
{isCheck
|
{isCheck ? (item as FiCheck).checkNumber : (item as PromissoryNote).noteNumber}
|
||||||
? (item as FiCheck).checkNumber
|
|
||||||
: (item as PromissoryNote).noteNumber}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button onClick={onClose} className="p-2 hover:bg-gray-100 rounded-md">
|
||||||
onClick={onClose}
|
|
||||||
className="p-2 hover:bg-gray-100 rounded-md"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -149,15 +115,13 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor(
|
||||||
item.status
|
item.status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getStatusLabel(item.status)}
|
{getStatusLabel(item.status)}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getTypeColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getTypeColor(item.type)}`}
|
||||||
item.type
|
|
||||||
)}`}
|
|
||||||
>
|
>
|
||||||
{getTypeLabel(item.type)}
|
{getTypeLabel(item.type)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -183,13 +147,9 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">
|
<span className="text-gray-600">{isCheck ? 'Çek No:' : 'Senet No:'}</span>
|
||||||
{isCheck ? "Çek No:" : "Senet No:"}
|
|
||||||
</span>
|
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{isCheck
|
{isCheck ? (item as FiCheck).checkNumber : (item as PromissoryNote).noteNumber}
|
||||||
? (item as FiCheck).checkNumber
|
|
||||||
: (item as PromissoryNote).noteNumber}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
|
|
@ -205,9 +165,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
{!isCheck && (item as PromissoryNote).location && (
|
{!isCheck && (item as PromissoryNote).location && (
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">Konum:</span>
|
<span className="text-gray-600">Konum:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{(item as PromissoryNote).location}</span>
|
||||||
{(item as PromissoryNote).location}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -223,35 +181,29 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">Düzenleme Tarihi:</span>
|
<span className="text-gray-600">Düzenleme Tarihi:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{new Date(item.issueDate).toLocaleDateString("tr-TR")}
|
{new Date(item.issueDate).toLocaleDateString('tr-TR')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">Vade Tarihi:</span>
|
<span className="text-gray-600">Vade Tarihi:</span>
|
||||||
<span
|
<span
|
||||||
className={`font-medium ${
|
className={`font-medium ${
|
||||||
isOverdue
|
isOverdue ? 'text-red-600' : isDueSoon ? 'text-orange-600' : 'text-gray-900'
|
||||||
? "text-red-600"
|
|
||||||
: isDueSoon
|
|
||||||
? "text-orange-600"
|
|
||||||
: "text-gray-900"
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{new Date(item.dueDate).toLocaleDateString("tr-TR")}
|
{new Date(item.dueDate).toLocaleDateString('tr-TR')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">Oluşturma Tarihi:</span>
|
<span className="text-gray-600">Oluşturma Tarihi:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{new Date(item.creationTime).toLocaleDateString("tr-TR")}
|
{new Date(item.creationTime).toLocaleDateString('tr-TR')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">Son Güncelleme:</span>
|
<span className="text-gray-600">Son Güncelleme:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{new Date(item.lastModificationTime).toLocaleDateString(
|
{new Date(item.lastModificationTime).toLocaleDateString('tr-TR')}
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -267,24 +219,16 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm">
|
||||||
<div>
|
<div>
|
||||||
<span className="text-gray-600 block text-sm">
|
<span className="text-gray-600 block text-sm">Banka Adı:</span>
|
||||||
Banka Adı:
|
<span className="font-medium">{(item as FiCheck).bankName}</span>
|
||||||
</span>
|
|
||||||
<span className="font-medium">
|
|
||||||
{(item as FiCheck).bankName}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-gray-600 block text-sm">Şube Adı:</span>
|
<span className="text-gray-600 block text-sm">Şube Adı:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{(item as FiCheck).branchName}</span>
|
||||||
{(item as FiCheck).branchName}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-gray-600 block text-sm">Hesap No:</span>
|
<span className="text-gray-600 block text-sm">Hesap No:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{(item as FiCheck).accountNumber}</span>
|
||||||
{(item as FiCheck).accountNumber}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -308,12 +252,9 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
</div>
|
</div>
|
||||||
{item.currentAccount && (
|
{item.currentAccount && (
|
||||||
<div className="mt-3 p-2 bg-blue-50 rounded-lg text-sm">
|
<div className="mt-3 p-2 bg-blue-50 rounded-lg text-sm">
|
||||||
<span className="text-gray-600 block text-sm">
|
<span className="text-gray-600 block text-sm">Bağlı Cari Hesap:</span>
|
||||||
Bağlı Cari Hesap:
|
|
||||||
</span>
|
|
||||||
<span className="font-medium text-blue-600">
|
<span className="font-medium text-blue-600">
|
||||||
{item.currentAccount.accountCode} -{" "}
|
{item.currentAccount.accountCode} - {item.currentAccount.accountCode}
|
||||||
{item.currentAccount.accountCode}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -330,9 +271,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
<div className="flex justify-between items-center p-3 bg-yellow-50 rounded-lg">
|
<div className="flex justify-between items-center p-3 bg-yellow-50 rounded-lg">
|
||||||
<span className="text-gray-700">Bankaya Verilme Tarihi:</span>
|
<span className="text-gray-700">Bankaya Verilme Tarihi:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{new Date((item as FiCheck).bankingDate!).toLocaleDateString(
|
{new Date((item as FiCheck).bankingDate!).toLocaleDateString('tr-TR')}
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -340,35 +279,27 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
<div className="flex justify-between items-center p-3 bg-green-50 rounded-lg">
|
<div className="flex justify-between items-center p-3 bg-green-50 rounded-lg">
|
||||||
<span className="text-gray-700">Tahsil Tarihi:</span>
|
<span className="text-gray-700">Tahsil Tarihi:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{new Date(item.collectionDate).toLocaleDateString("tr-TR")}
|
{new Date(item.collectionDate).toLocaleDateString('tr-TR')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{item.endorsedTo && (
|
{item.endorsedTo && (
|
||||||
<div className="flex justify-between items-center p-3 bg-purple-50 rounded-lg">
|
<div className="flex justify-between items-center p-3 bg-purple-50 rounded-lg">
|
||||||
<span className="text-gray-700">
|
<span className="text-gray-700">Ciro Edildiği Kişi/Kuruluş:</span>
|
||||||
Ciro Edildiği Kişi/Kuruluş:
|
|
||||||
</span>
|
|
||||||
<span className="font-medium">{item.endorsedTo}</span>
|
<span className="font-medium">{item.endorsedTo}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(!isCheck || !(item as FiCheck).bankingDate) &&
|
{(!isCheck || !(item as FiCheck).bankingDate) &&
|
||||||
!item.collectionDate &&
|
!item.collectionDate &&
|
||||||
!item.endorsedTo && (
|
!item.endorsedTo && <p className="text-gray-500 italic">Henüz işlem yapılmamış</p>}
|
||||||
<p className="text-gray-500 italic">Henüz işlem yapılmamış</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Notlar */}
|
{/* Notlar */}
|
||||||
{item.notes && (
|
{item.notes && (
|
||||||
<div className="bg-gray-50 p-3 rounded-lg">
|
<div className="bg-gray-50 p-3 rounded-lg">
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-2">
|
<h3 className="text-base font-medium text-gray-900 mb-2">Notlar</h3>
|
||||||
Notlar
|
<p className="text-sm text-gray-700 whitespace-pre-wrap">{item.notes}</p>
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-gray-700 whitespace-pre-wrap">
|
|
||||||
{item.notes}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -384,7 +315,7 @@ const CheckNoteDetails: React.FC<CheckNoteDetailsProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CheckNoteDetails;
|
export default CheckNoteDetails
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ import {
|
||||||
PromissoryNote,
|
PromissoryNote,
|
||||||
CheckStatusEnum,
|
CheckStatusEnum,
|
||||||
NoteStatusEnum,
|
NoteStatusEnum,
|
||||||
CheckTypeEnum,
|
TypeEnum,
|
||||||
NoteTypeEnum,
|
|
||||||
FiCurrentAccount,
|
FiCurrentAccount,
|
||||||
} from '../../../types/fi'
|
} from '../../../types/fi'
|
||||||
import DataTable, { Column } from '../../../components/common/DataTable'
|
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||||
|
|
@ -71,7 +70,7 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [selectedCheckStatus, setSelectedCheckStatus] = useState<CheckStatusEnum | 'all'>('all')
|
const [selectedCheckStatus, setSelectedCheckStatus] = useState<CheckStatusEnum | 'all'>('all')
|
||||||
const [selectedNoteStatus, setSelectedNoteStatus] = useState<NoteStatusEnum | 'all'>('all')
|
const [selectedNoteStatus, setSelectedNoteStatus] = useState<NoteStatusEnum | 'all'>('all')
|
||||||
const [selectedType, setSelectedType] = useState<CheckTypeEnum | NoteTypeEnum | 'all'>('all')
|
const [selectedType, setSelectedType] = useState<TypeEnum | 'all'>('all')
|
||||||
const [sortBy, setSortBy] = useState<'dueDate' | 'amount' | 'issueDate'>('dueDate')
|
const [sortBy, setSortBy] = useState<'dueDate' | 'amount' | 'issueDate'>('dueDate')
|
||||||
|
|
||||||
// Dialog states
|
// Dialog states
|
||||||
|
|
@ -242,19 +241,19 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const getTypeLabel = (type: CheckTypeEnum | NoteTypeEnum) => {
|
const getTypeLabel = (type: TypeEnum) => {
|
||||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
if (type === TypeEnum.Received) {
|
||||||
return 'Alınan'
|
return 'Alınan'
|
||||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
} else if (type === TypeEnum.Issued) {
|
||||||
return 'Verilen'
|
return 'Verilen'
|
||||||
}
|
}
|
||||||
return 'Bilinmeyen'
|
return 'Bilinmeyen'
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTypeColor = (type: CheckTypeEnum | NoteTypeEnum) => {
|
const getTypeColor = (type: TypeEnum) => {
|
||||||
if (type === CheckTypeEnum.Received || type === NoteTypeEnum.Received) {
|
if (type === TypeEnum.Received) {
|
||||||
return 'bg-green-100 text-green-800'
|
return 'bg-green-100 text-green-800'
|
||||||
} else if (type === CheckTypeEnum.Issued || type === NoteTypeEnum.Issued) {
|
} else if (type === TypeEnum.Issued) {
|
||||||
return 'bg-orange-100 text-orange-800'
|
return 'bg-orange-100 text-orange-800'
|
||||||
}
|
}
|
||||||
return 'bg-gray-100 text-gray-800'
|
return 'bg-gray-100 text-gray-800'
|
||||||
|
|
@ -593,11 +592,11 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
||||||
const totalNoteAmount = promissoryNotes.reduce((sum, note) => sum + note.amount, 0)
|
const totalNoteAmount = promissoryNotes.reduce((sum, note) => sum + note.amount, 0)
|
||||||
|
|
||||||
const receivedCheckAmount = checks
|
const receivedCheckAmount = checks
|
||||||
.filter((c) => c.type === CheckTypeEnum.Received && c.status !== CheckStatusEnum.Collected)
|
.filter((c) => c.type === TypeEnum.Received && c.status !== CheckStatusEnum.Collected)
|
||||||
.reduce((sum, c) => sum + c.amount, 0)
|
.reduce((sum, c) => sum + c.amount, 0)
|
||||||
|
|
||||||
const receivedNoteAmount = promissoryNotes
|
const receivedNoteAmount = promissoryNotes
|
||||||
.filter((n) => n.type === NoteTypeEnum.Received && n.status !== NoteStatusEnum.Collected)
|
.filter((n) => n.type === TypeEnum.Received && n.status !== NoteStatusEnum.Collected)
|
||||||
.reduce((sum, n) => sum + n.amount, 0)
|
.reduce((sum, n) => sum + n.amount, 0)
|
||||||
|
|
||||||
// Due items
|
// Due items
|
||||||
|
|
@ -756,9 +755,7 @@ const CheckNoteManagement: React.FC<CheckNoteManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={selectedType}
|
value={selectedType}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSelectedType(e.target.value as TypeEnum | 'all')}
|
||||||
setSelectedType(e.target.value as CheckTypeEnum | NoteTypeEnum | 'all')
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Türler</option>
|
<option value="all">Tüm Türler</option>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,15 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import {
|
import { FaTimes, FaUser, FaBuilding, FaCreditCard, FaPhoneAlt } from 'react-icons/fa'
|
||||||
FaTimes,
|
import { FiCurrentAccount, AccountTypeEnum, RiskGroupEnum } from '../../../types/fi'
|
||||||
FaUser,
|
import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
||||||
FaBuilding,
|
import { getAccountTypeText, getRiskGroupText } from '../../../utils/erp'
|
||||||
FaCreditCard,
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
FaPhoneAlt,
|
|
||||||
} from "react-icons/fa";
|
|
||||||
import {
|
|
||||||
FiCurrentAccount,
|
|
||||||
AccountTypeEnum,
|
|
||||||
RiskGroupEnum,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
import { mockBusinessParties } from "../../../mocks/mockBusinessParties";
|
|
||||||
import { getAccountTypeText, getRiskGroupText } from "../../../utils/erp";
|
|
||||||
|
|
||||||
interface CurrentAccountFormProps {
|
interface CurrentAccountFormProps {
|
||||||
account?: FiCurrentAccount;
|
account?: FiCurrentAccount
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (account: Partial<FiCurrentAccount>) => void;
|
onSave: (account: Partial<FiCurrentAccount>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
|
|
@ -29,26 +20,26 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState<
|
const [formData, setFormData] = useState<
|
||||||
Partial<FiCurrentAccount> & {
|
Partial<FiCurrentAccount> & {
|
||||||
id?: string;
|
id?: string
|
||||||
}
|
}
|
||||||
>({
|
>({
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
businessPartyId: "",
|
businessPartyId: '',
|
||||||
type: AccountTypeEnum.Customer,
|
type: AccountTypeEnum.Customer,
|
||||||
contactPerson: "",
|
contactPerson: '',
|
||||||
phone: "",
|
phone: '',
|
||||||
email: "",
|
email: '',
|
||||||
address: "",
|
address: '',
|
||||||
taxNumber: "",
|
taxNumber: '',
|
||||||
taxOffice: "",
|
taxOffice: '',
|
||||||
creditLimit: 0,
|
creditLimit: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
riskGroup: RiskGroupEnum.Low,
|
riskGroup: RiskGroupEnum.Low,
|
||||||
paymentTerm: 30,
|
paymentTerm: 30,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (account) {
|
if (account) {
|
||||||
|
|
@ -56,100 +47,95 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
...account,
|
...account,
|
||||||
creditLimit: account.creditLimit || 0,
|
creditLimit: account.creditLimit || 0,
|
||||||
paymentTerm: account.paymentTerm || 30,
|
paymentTerm: account.paymentTerm || 30,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
accountCode: "",
|
accountCode: '',
|
||||||
businessPartyId: "",
|
businessPartyId: '',
|
||||||
type: AccountTypeEnum.Customer,
|
type: AccountTypeEnum.Customer,
|
||||||
contactPerson: "",
|
contactPerson: '',
|
||||||
phone: "",
|
phone: '',
|
||||||
email: "",
|
email: '',
|
||||||
address: "",
|
address: '',
|
||||||
taxNumber: "",
|
taxNumber: '',
|
||||||
taxOffice: "",
|
taxOffice: '',
|
||||||
creditLimit: 0,
|
creditLimit: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
riskGroup: RiskGroupEnum.Low,
|
riskGroup: RiskGroupEnum.Low,
|
||||||
paymentTerm: 30,
|
paymentTerm: 30,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setErrors({});
|
setErrors({})
|
||||||
}, [account, isOpen]);
|
}, [account, isOpen])
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
e: React.ChangeEvent<
|
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
||||||
>
|
|
||||||
) => {
|
) => {
|
||||||
const { name, value, type } = e.target;
|
const { name, value, type } = e.target
|
||||||
let parsedValue: string | number | boolean = value;
|
let parsedValue: string | number | boolean = value
|
||||||
|
|
||||||
if (type === "number") {
|
if (type === 'number') {
|
||||||
parsedValue = value === "" ? 0 : parseFloat(value);
|
parsedValue = value === '' ? 0 : parseFloat(value)
|
||||||
} else if (type === "checkbox") {
|
} else if (type === 'checkbox') {
|
||||||
parsedValue = (e.target as HTMLInputElement).checked;
|
parsedValue = (e.target as HTMLInputElement).checked
|
||||||
}
|
}
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: parsedValue,
|
[name]: parsedValue,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// Clear error when user starts typing
|
// Clear error when user starts typing
|
||||||
if (errors[name]) {
|
if (errors[name]) {
|
||||||
setErrors((prev) => ({
|
setErrors((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: "",
|
[name]: '',
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const newErrors: Record<string, string> = {};
|
const newErrors: Record<string, string> = {}
|
||||||
|
|
||||||
if (!formData.accountCode?.trim()) {
|
if (!formData.accountCode?.trim()) {
|
||||||
newErrors.accountCode = "Hesap kodu zorunludur";
|
newErrors.accountCode = 'Hesap kodu zorunludur'
|
||||||
}
|
}
|
||||||
if (!formData.businessPartyId?.trim()) {
|
if (!formData.businessPartyId?.trim()) {
|
||||||
newErrors.businessPartyId = "Ünvan zorunludur";
|
newErrors.businessPartyId = 'Ünvan zorunludur'
|
||||||
}
|
}
|
||||||
if (formData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
if (formData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
||||||
newErrors.email = "Geçerli bir e-posta adresi giriniz";
|
newErrors.email = 'Geçerli bir e-posta adresi giriniz'
|
||||||
}
|
}
|
||||||
if (formData.creditLimit && formData.creditLimit < 0) {
|
if (formData.creditLimit && formData.creditLimit < 0) {
|
||||||
newErrors.creditLimit = "Kredi limiti negatif olamaz";
|
newErrors.creditLimit = 'Kredi limiti negatif olamaz'
|
||||||
}
|
}
|
||||||
if (formData.paymentTerm && formData.paymentTerm < 0) {
|
if (formData.paymentTerm && formData.paymentTerm < 0) {
|
||||||
newErrors.paymentTerm = "Ödeme vadesi negatif olamaz";
|
newErrors.paymentTerm = 'Ödeme vadesi negatif olamaz'
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors)
|
||||||
return Object.keys(newErrors).length === 0;
|
return Object.keys(newErrors).length === 0
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
onSave(formData);
|
onSave(formData)
|
||||||
onClose();
|
onClose()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-lg w-full max-w-3xl max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg w-full max-w-3xl max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-4 border-b">
|
<div className="flex items-center justify-between p-4 border-b">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{account ? "Cari Hesap Düzenle" : "Yeni Cari Hesap"}
|
{account ? 'Cari Hesap Düzenle' : 'Yeni Cari Hesap'}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5" />
|
<FaTimes className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -164,34 +150,28 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Kodu *</label>
|
||||||
Hesap Kodu *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="accountCode"
|
name="accountCode"
|
||||||
value={formData.accountCode || ""}
|
value={formData.accountCode || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.accountCode ? "border-red-500" : "border-gray-300"
|
errors.accountCode ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="CA001"
|
placeholder="CA001"
|
||||||
/>
|
/>
|
||||||
{errors.accountCode && (
|
{errors.accountCode && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.accountCode}</p>
|
||||||
{errors.accountCode}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Ünvan *</label>
|
||||||
Ünvan *
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<select
|
<select
|
||||||
name="businessPartyId"
|
name="businessPartyId"
|
||||||
value={formData.businessPartyId || ""}
|
value={formData.businessPartyId || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
|
|
@ -203,15 +183,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.title && (
|
{errors.title && <p className="text-red-500 text-xs mt-1">{errors.title}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.title}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Hesap Türü</label>
|
||||||
Hesap Türü
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="type"
|
name="type"
|
||||||
value={formData.type}
|
value={formData.type}
|
||||||
|
|
@ -227,13 +203,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Yetkili Kişi</label>
|
||||||
Yetkili Kişi
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="contactPerson"
|
name="contactPerson"
|
||||||
value={formData.contactPerson || ""}
|
value={formData.contactPerson || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Yetkili kişi adı"
|
placeholder="Yetkili kişi adı"
|
||||||
|
|
@ -249,13 +223,11 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
|
||||||
Telefon
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="phone"
|
name="phone"
|
||||||
value={formData.phone || ""}
|
value={formData.phone || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="+90 212 555 1234"
|
placeholder="+90 212 555 1234"
|
||||||
|
|
@ -263,31 +235,25 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
|
||||||
E-posta
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
value={formData.email || ""}
|
value={formData.email || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.email ? "border-red-500" : "border-gray-300"
|
errors.email ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="info@company.com"
|
placeholder="info@company.com"
|
||||||
/>
|
/>
|
||||||
{errors.email && (
|
{errors.email && <p className="text-red-500 text-xs mt-1">{errors.email}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.email}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Adres</label>
|
||||||
Adres
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
name="address"
|
name="address"
|
||||||
value={formData.address || ""}
|
value={formData.address || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
|
|
@ -303,7 +269,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="taxNumber"
|
name="taxNumber"
|
||||||
value={formData.taxNumber || ""}
|
value={formData.taxNumber || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="1234567890"
|
placeholder="1234567890"
|
||||||
|
|
@ -317,7 +283,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="taxOffice"
|
name="taxOffice"
|
||||||
value={formData.taxOffice || ""}
|
value={formData.taxOffice || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Beylikdüzü V.D."
|
placeholder="Beylikdüzü V.D."
|
||||||
|
|
@ -346,14 +312,12 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
min="0"
|
min="0"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.creditLimit ? "border-red-500" : "border-gray-300"
|
errors.creditLimit ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="0.00"
|
placeholder="0.00"
|
||||||
/>
|
/>
|
||||||
{errors.creditLimit && (
|
{errors.creditLimit && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.creditLimit}</p>
|
||||||
{errors.creditLimit}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -367,19 +331,18 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY - Türk Lirası</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD - Amerikan Doları</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR - Euro</option>
|
{currency.value} - {currency.label}
|
||||||
<option value="GBP">GBP - İngiliz Sterlini</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Risk Grubu</label>
|
||||||
Risk Grubu
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="riskGroup"
|
name="riskGroup"
|
||||||
value={formData.riskGroup}
|
value={formData.riskGroup}
|
||||||
|
|
@ -405,14 +368,12 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
min="0"
|
min="0"
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.paymentTerm ? "border-red-500" : "border-gray-300"
|
errors.paymentTerm ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="30"
|
placeholder="30"
|
||||||
/>
|
/>
|
||||||
{errors.paymentTerm && (
|
{errors.paymentTerm && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.paymentTerm}</p>
|
||||||
{errors.paymentTerm}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -433,9 +394,7 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<label className="ml-2 block text-sm text-gray-700">
|
<label className="ml-2 block text-sm text-gray-700">Aktif hesap</label>
|
||||||
Aktif hesap
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -453,13 +412,13 @@ const CurrentAccountForm: React.FC<CurrentAccountFormProps> = ({
|
||||||
type="submit"
|
type="submit"
|
||||||
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
||||||
>
|
>
|
||||||
{account ? "Güncelle" : "Ekle"}
|
{account ? 'Güncelle' : 'Ekle'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CurrentAccountForm;
|
export default CurrentAccountForm
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaTimes, FaFileInvoice, FaMoneyBill } from "react-icons/fa";
|
import { FaTimes, FaFileInvoice, FaMoneyBill } from 'react-icons/fa'
|
||||||
import {
|
import { FiCurrentAccountMovement, FiDocumentTypeEnum, FiCurrentAccount } from '../../../types/fi'
|
||||||
FiCurrentAccountMovement,
|
import { getFiDocumentTypeText } from '../../../utils/erp'
|
||||||
FiDocumentTypeEnum,
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
FiCurrentAccount,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
import { getFiDocumentTypeText } from "../../../utils/erp";
|
|
||||||
|
|
||||||
interface CurrentAccountMovementFormProps {
|
interface CurrentAccountMovementFormProps {
|
||||||
movement?: FiCurrentAccountMovement;
|
movement?: FiCurrentAccountMovement
|
||||||
accounts: FiCurrentAccount[];
|
accounts: FiCurrentAccount[]
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (movement: Partial<FiCurrentAccountMovement>) => void;
|
onSave: (movement: Partial<FiCurrentAccountMovement>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
|
|
@ -24,22 +21,22 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState<
|
const [formData, setFormData] = useState<
|
||||||
Partial<FiCurrentAccountMovement> & {
|
Partial<FiCurrentAccountMovement> & {
|
||||||
id?: string;
|
id?: string
|
||||||
}
|
}
|
||||||
>({
|
>({
|
||||||
accountId: "",
|
accountId: '',
|
||||||
transactionDate: new Date(),
|
transactionDate: new Date(),
|
||||||
description: "",
|
description: '',
|
||||||
referenceNumber: "",
|
referenceNumber: '',
|
||||||
documentType: FiDocumentTypeEnum.Invoice,
|
documentType: FiDocumentTypeEnum.Invoice,
|
||||||
documentNumber: "",
|
documentNumber: '',
|
||||||
debitAmount: 0,
|
debitAmount: 0,
|
||||||
creditAmount: 0,
|
creditAmount: 0,
|
||||||
balance: 0,
|
balance: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
});
|
})
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (movement) {
|
if (movement) {
|
||||||
|
|
@ -48,111 +45,100 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
debitAmount: movement.debitAmount || 0,
|
debitAmount: movement.debitAmount || 0,
|
||||||
creditAmount: movement.creditAmount || 0,
|
creditAmount: movement.creditAmount || 0,
|
||||||
balance: movement.balance || 0,
|
balance: movement.balance || 0,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
accountId: "",
|
accountId: '',
|
||||||
transactionDate: new Date(),
|
transactionDate: new Date(),
|
||||||
description: "",
|
description: '',
|
||||||
referenceNumber: "",
|
referenceNumber: '',
|
||||||
documentType: FiDocumentTypeEnum.Invoice,
|
documentType: FiDocumentTypeEnum.Invoice,
|
||||||
documentNumber: "",
|
documentNumber: '',
|
||||||
debitAmount: 0,
|
debitAmount: 0,
|
||||||
creditAmount: 0,
|
creditAmount: 0,
|
||||||
balance: 0,
|
balance: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setErrors({});
|
setErrors({})
|
||||||
}, [movement, isOpen]);
|
}, [movement, isOpen])
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
e: React.ChangeEvent<
|
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
||||||
>
|
|
||||||
) => {
|
) => {
|
||||||
const { name, value, type } = e.target;
|
const { name, value, type } = e.target
|
||||||
let parsedValue: string | number | Date = value;
|
let parsedValue: string | number | Date = value
|
||||||
|
|
||||||
if (type === "number") {
|
if (type === 'number') {
|
||||||
parsedValue = value === "" ? 0 : parseFloat(value);
|
parsedValue = value === '' ? 0 : parseFloat(value)
|
||||||
} else if (type === "date") {
|
} else if (type === 'date') {
|
||||||
parsedValue = new Date(value);
|
parsedValue = new Date(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: parsedValue,
|
[name]: parsedValue,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// Clear error when user starts typing
|
// Clear error when user starts typing
|
||||||
if (errors[name]) {
|
if (errors[name]) {
|
||||||
setErrors((prev) => ({
|
setErrors((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: "",
|
[name]: '',
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const newErrors: Record<string, string> = {};
|
const newErrors: Record<string, string> = {}
|
||||||
|
|
||||||
if (!formData.accountId) {
|
if (!formData.accountId) {
|
||||||
newErrors.accountId = "Cari hesap seçimi zorunludur";
|
newErrors.accountId = 'Cari hesap seçimi zorunludur'
|
||||||
}
|
}
|
||||||
if (!formData.description?.trim()) {
|
if (!formData.description?.trim()) {
|
||||||
newErrors.description = "Açıklama zorunludur";
|
newErrors.description = 'Açıklama zorunludur'
|
||||||
}
|
}
|
||||||
if (!formData.transactionDate) {
|
if (!formData.transactionDate) {
|
||||||
newErrors.transactionDate = "İşlem tarihi zorunludur";
|
newErrors.transactionDate = 'İşlem tarihi zorunludur'
|
||||||
}
|
}
|
||||||
if (
|
if ((formData.debitAmount || 0) === 0 && (formData.creditAmount || 0) === 0) {
|
||||||
(formData.debitAmount || 0) === 0 &&
|
newErrors.amount = 'Borç veya alacak tutarından biri girilmelidir'
|
||||||
(formData.creditAmount || 0) === 0
|
|
||||||
) {
|
|
||||||
newErrors.amount = "Borç veya alacak tutarından biri girilmelidir";
|
|
||||||
}
|
}
|
||||||
if ((formData.debitAmount || 0) > 0 && (formData.creditAmount || 0) > 0) {
|
if ((formData.debitAmount || 0) > 0 && (formData.creditAmount || 0) > 0) {
|
||||||
newErrors.amount = "Borç ve alacak tutarı aynı anda girilemez";
|
newErrors.amount = 'Borç ve alacak tutarı aynı anda girilemez'
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors)
|
||||||
return Object.keys(newErrors).length === 0;
|
return Object.keys(newErrors).length === 0
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
// Calculate balance based on debit/credit amounts
|
// Calculate balance based on debit/credit amounts
|
||||||
const balance =
|
const balance = (formData.debitAmount || 0) - (formData.creditAmount || 0)
|
||||||
(formData.debitAmount || 0) - (formData.creditAmount || 0);
|
|
||||||
|
|
||||||
const movementData = {
|
const movementData = {
|
||||||
...formData,
|
...formData,
|
||||||
balance,
|
balance,
|
||||||
creationTime: movement?.creationTime || new Date(),
|
creationTime: movement?.creationTime || new Date(),
|
||||||
};
|
}
|
||||||
|
|
||||||
onSave(movementData);
|
onSave(movementData)
|
||||||
onClose();
|
onClose()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-4 border-b">
|
<div className="flex items-center justify-between p-4 border-b">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{movement
|
{movement ? 'Cari Hesap Hareketi Düzenle' : 'Yeni Cari Hesap Hareketi'}
|
||||||
? "Cari Hesap Hareketi Düzenle"
|
|
||||||
: "Yeni Cari Hesap Hareketi"}
|
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5" />
|
<FaTimes className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -167,15 +153,13 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap *</label>
|
||||||
Cari Hesap *
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="accountId"
|
name="accountId"
|
||||||
value={formData.accountId || ""}
|
value={formData.accountId || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.accountId ? "border-red-500" : "border-gray-300"
|
errors.accountId ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value="">Cari hesap seçiniz</option>
|
<option value="">Cari hesap seçiniz</option>
|
||||||
|
|
@ -186,9 +170,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.accountId && (
|
{errors.accountId && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.accountId}</p>
|
||||||
{errors.accountId}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -201,29 +183,21 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
name="transactionDate"
|
name="transactionDate"
|
||||||
value={
|
value={
|
||||||
formData.transactionDate
|
formData.transactionDate
|
||||||
? new Date(formData.transactionDate)
|
? new Date(formData.transactionDate).toISOString().split('T')[0]
|
||||||
.toISOString()
|
: ''
|
||||||
.split("T")[0]
|
|
||||||
: ""
|
|
||||||
}
|
}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.transactionDate
|
errors.transactionDate ? 'border-red-500' : 'border-gray-300'
|
||||||
? "border-red-500"
|
|
||||||
: "border-gray-300"
|
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
{errors.transactionDate && (
|
{errors.transactionDate && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.transactionDate}</p>
|
||||||
{errors.transactionDate}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Belge Türü</label>
|
||||||
Belge Türü
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="documentType"
|
name="documentType"
|
||||||
value={formData.documentType}
|
value={formData.documentType}
|
||||||
|
|
@ -246,7 +220,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="referenceNumber"
|
name="referenceNumber"
|
||||||
value={formData.referenceNumber || ""}
|
value={formData.referenceNumber || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="REF001"
|
placeholder="REF001"
|
||||||
|
|
@ -254,13 +228,11 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Belge No</label>
|
||||||
Belge No
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="documentNumber"
|
name="documentNumber"
|
||||||
value={formData.documentNumber || ""}
|
value={formData.documentNumber || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="DOC001"
|
placeholder="DOC001"
|
||||||
|
|
@ -277,9 +249,7 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Borç Tutarı</label>
|
||||||
Borç Tutarı
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
name="debitAmount"
|
name="debitAmount"
|
||||||
|
|
@ -309,19 +279,18 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||||
Para Birimi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="currency"
|
name="currency"
|
||||||
value={formData.currency}
|
value={formData.currency}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY - Türk Lirası</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD - Amerikan Doları</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR - Euro</option>
|
{currency.value} - {currency.label}
|
||||||
<option value="GBP">GBP - İngiliz Sterlini</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -333,37 +302,34 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
|
|
||||||
<div className="p-2 bg-blue-50 border border-blue-200 rounded-md">
|
<div className="p-2 bg-blue-50 border border-blue-200 rounded-md">
|
||||||
<p className="text-blue-800 text-sm">
|
<p className="text-blue-800 text-sm">
|
||||||
<strong>Hesaplanan Bakiye:</strong>{" "}
|
<strong>Hesaplanan Bakiye:</strong>{' '}
|
||||||
{(
|
{((formData.debitAmount || 0) - (formData.creditAmount || 0)).toLocaleString(
|
||||||
(formData.debitAmount || 0) - (formData.creditAmount || 0)
|
'tr-TR',
|
||||||
).toLocaleString("tr-TR", {
|
{
|
||||||
style: "currency",
|
style: 'currency',
|
||||||
currency: formData.currency || "TRY",
|
currency: formData.currency || 'TRY',
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
})}
|
},
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Açıklama */}
|
{/* Açıklama */}
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama *</label>
|
||||||
Açıklama *
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
name="description"
|
name="description"
|
||||||
value={formData.description || ""}
|
value={formData.description || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
rows={3}
|
rows={3}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.description ? "border-red-500" : "border-gray-300"
|
errors.description ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Hareket açıklaması"
|
placeholder="Hareket açıklaması"
|
||||||
/>
|
/>
|
||||||
{errors.description && (
|
{errors.description && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.description}</p>
|
||||||
{errors.description}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -381,13 +347,13 @@ const CurrentAccountMovementForm: React.FC<CurrentAccountMovementFormProps> = ({
|
||||||
type="submit"
|
type="submit"
|
||||||
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
|
||||||
>
|
>
|
||||||
{movement ? "Güncelle" : "Ekle"}
|
{movement ? 'Güncelle' : 'Ekle'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CurrentAccountMovementForm;
|
export default CurrentAccountMovementForm
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,27 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from "react-icons/fa";
|
import { FaSave, FaTimes, FaPlus, FaTrash, FaFileAlt } from 'react-icons/fa'
|
||||||
import {
|
import {
|
||||||
FiInvoice,
|
FiInvoice,
|
||||||
FiInvoiceItem,
|
FiInvoiceItem,
|
||||||
InvoiceTypeEnum,
|
InvoiceTypeEnum,
|
||||||
InvoiceStatusEnum,
|
InvoiceStatusEnum,
|
||||||
PaymentStatusEnum,
|
PaymentStatusEnum,
|
||||||
} from "../../../types/fi";
|
} from '../../../types/fi'
|
||||||
import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts";
|
import { mockCurrentAccounts } from '../../../mocks/mockCurrentAccounts'
|
||||||
|
import { getInvoiceTypeText } from '@/utils/erp'
|
||||||
|
|
||||||
interface InvoiceFormProps {
|
interface InvoiceFormProps {
|
||||||
invoice?: FiInvoice;
|
invoice?: FiInvoice
|
||||||
onSave: (invoice: Partial<FiInvoice>) => void;
|
onSave: (invoice: Partial<FiInvoice>) => void
|
||||||
onCancel: () => void;
|
onCancel: () => void
|
||||||
isVisible: boolean;
|
isVisible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
const InvoiceForm: React.FC<InvoiceFormProps> = ({ invoice, onSave, onCancel, isVisible }) => {
|
||||||
invoice,
|
|
||||||
onSave,
|
|
||||||
onCancel,
|
|
||||||
isVisible,
|
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState<Partial<FiInvoice>>({
|
const [formData, setFormData] = useState<Partial<FiInvoice>>({
|
||||||
invoiceNumber: "",
|
invoiceNumber: '',
|
||||||
invoiceType: InvoiceTypeEnum.Sales,
|
invoiceType: InvoiceTypeEnum.Sales,
|
||||||
currentAccountId: "",
|
currentAccountId: '',
|
||||||
invoiceDate: new Date(),
|
invoiceDate: new Date(),
|
||||||
dueDate: new Date(),
|
dueDate: new Date(),
|
||||||
deliveryDate: new Date(),
|
deliveryDate: new Date(),
|
||||||
|
|
@ -35,22 +31,22 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
totalAmount: 0,
|
totalAmount: 0,
|
||||||
paidAmount: 0,
|
paidAmount: 0,
|
||||||
remainingAmount: 0,
|
remainingAmount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: InvoiceStatusEnum.Draft,
|
status: InvoiceStatusEnum.Draft,
|
||||||
paymentStatus: PaymentStatusEnum.Unpaid,
|
paymentStatus: PaymentStatusEnum.Unpaid,
|
||||||
items: [],
|
items: [],
|
||||||
waybillNumber: "",
|
waybillNumber: '',
|
||||||
notes: "",
|
notes: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
const [newItem, setNewItem] = useState<Partial<FiInvoiceItem>>({
|
const [newItem, setNewItem] = useState<Partial<FiInvoiceItem>>({
|
||||||
description: "",
|
description: '',
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
unitPrice: 0,
|
unitPrice: 0,
|
||||||
taxRate: 18,
|
taxRate: 18,
|
||||||
discountRate: 0,
|
discountRate: 0,
|
||||||
unit: "Adet",
|
unit: 'Adet',
|
||||||
});
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (invoice) {
|
if (invoice) {
|
||||||
|
|
@ -58,18 +54,17 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
...invoice,
|
...invoice,
|
||||||
invoiceDate: new Date(invoice.invoiceDate),
|
invoiceDate: new Date(invoice.invoiceDate),
|
||||||
dueDate: new Date(invoice.dueDate),
|
dueDate: new Date(invoice.dueDate),
|
||||||
deliveryDate: invoice.deliveryDate
|
deliveryDate: invoice.deliveryDate ? new Date(invoice.deliveryDate) : new Date(),
|
||||||
? new Date(invoice.deliveryDate)
|
})
|
||||||
: new Date(),
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// Generate new invoice number
|
// Generate new invoice number
|
||||||
const now = new Date();
|
const now = new Date()
|
||||||
const year = now.getFullYear();
|
const year = now.getFullYear()
|
||||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||||
const invoiceNumber = `FT${year}${month}${String(
|
const invoiceNumber = `FT${year}${month}${String(Math.floor(Math.random() * 10000)).padStart(
|
||||||
Math.floor(Math.random() * 10000)
|
4,
|
||||||
).padStart(4, "0")}`;
|
'0',
|
||||||
|
)}`
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
|
|
@ -77,58 +72,50 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
invoiceDate: now,
|
invoiceDate: now,
|
||||||
dueDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), // 30 days
|
dueDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), // 30 days
|
||||||
deliveryDate: now,
|
deliveryDate: now,
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
}, [invoice]);
|
}, [invoice])
|
||||||
|
|
||||||
const calculateItemTotal = (item: Partial<FiInvoiceItem>) => {
|
const calculateItemTotal = (item: Partial<FiInvoiceItem>) => {
|
||||||
const subtotal = (item.quantity || 0) * (item.unitPrice || 0);
|
const subtotal = (item.quantity || 0) * (item.unitPrice || 0)
|
||||||
const discountAmount = subtotal * ((item.discountRate || 0) / 100);
|
const discountAmount = subtotal * ((item.discountRate || 0) / 100)
|
||||||
const taxableAmount = subtotal - discountAmount;
|
const taxableAmount = subtotal - discountAmount
|
||||||
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100);
|
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100)
|
||||||
return taxableAmount + taxAmount;
|
return taxableAmount + taxAmount
|
||||||
};
|
}
|
||||||
|
|
||||||
const calculateInvoiceTotals = (items: FiInvoiceItem[]) => {
|
const calculateInvoiceTotals = (items: FiInvoiceItem[]) => {
|
||||||
const subtotal = items.reduce(
|
const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0)
|
||||||
(sum, item) => sum + item.quantity * item.unitPrice,
|
const discountAmount = items.reduce((sum, item) => sum + item.discountAmount, 0)
|
||||||
0
|
const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0)
|
||||||
);
|
const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0)
|
||||||
const discountAmount = items.reduce(
|
|
||||||
(sum, item) => sum + item.discountAmount,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0);
|
|
||||||
const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subtotal,
|
subtotal,
|
||||||
discountAmount,
|
discountAmount,
|
||||||
taxAmount,
|
taxAmount,
|
||||||
totalAmount,
|
totalAmount,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleAddItem = () => {
|
const handleAddItem = () => {
|
||||||
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
|
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
|
||||||
alert("Lütfen ürün bilgilerini doldurun");
|
alert('Lütfen ürün bilgilerini doldurun')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const item: FiInvoiceItem = {
|
const item: FiInvoiceItem = {
|
||||||
id: Date.now().toString(),
|
id: Date.now().toString(),
|
||||||
invoiceId: formData.id || "",
|
invoiceId: formData.id || '',
|
||||||
description: newItem.description!,
|
description: newItem.description!,
|
||||||
quantity: newItem.quantity!,
|
quantity: newItem.quantity!,
|
||||||
unitPrice: newItem.unitPrice!,
|
unitPrice: newItem.unitPrice!,
|
||||||
unit: newItem.unit || "Adet",
|
unit: newItem.unit || 'Adet',
|
||||||
taxRate: newItem.taxRate || 18,
|
taxRate: newItem.taxRate || 18,
|
||||||
discountRate: newItem.discountRate || 0,
|
discountRate: newItem.discountRate || 0,
|
||||||
lineTotal: calculateItemTotal(newItem),
|
lineTotal: calculateItemTotal(newItem),
|
||||||
discountAmount:
|
discountAmount:
|
||||||
(newItem.quantity || 0) *
|
(newItem.quantity || 0) * (newItem.unitPrice || 0) * ((newItem.discountRate || 0) / 100),
|
||||||
(newItem.unitPrice || 0) *
|
|
||||||
((newItem.discountRate || 0) / 100),
|
|
||||||
taxAmount:
|
taxAmount:
|
||||||
((newItem.quantity || 0) * (newItem.unitPrice || 0) -
|
((newItem.quantity || 0) * (newItem.unitPrice || 0) -
|
||||||
(newItem.quantity || 0) *
|
(newItem.quantity || 0) *
|
||||||
|
|
@ -136,50 +123,49 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
((newItem.discountRate || 0) / 100)) *
|
((newItem.discountRate || 0) / 100)) *
|
||||||
((newItem.taxRate || 0) / 100),
|
((newItem.taxRate || 0) / 100),
|
||||||
netAmount: calculateItemTotal(newItem),
|
netAmount: calculateItemTotal(newItem),
|
||||||
};
|
}
|
||||||
|
|
||||||
const updatedItems = [...(formData.items || []), item];
|
const updatedItems = [...(formData.items || []), item]
|
||||||
const totals = calculateInvoiceTotals(updatedItems);
|
const totals = calculateInvoiceTotals(updatedItems)
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
items: updatedItems,
|
items: updatedItems,
|
||||||
...totals,
|
...totals,
|
||||||
remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
|
remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
|
||||||
}));
|
}))
|
||||||
|
|
||||||
setNewItem({
|
setNewItem({
|
||||||
description: "",
|
description: '',
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
unitPrice: 0,
|
unitPrice: 0,
|
||||||
taxRate: 18,
|
taxRate: 18,
|
||||||
discountRate: 0,
|
discountRate: 0,
|
||||||
unit: "Adet",
|
unit: 'Adet',
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleRemoveItem = (itemId: string) => {
|
const handleRemoveItem = (itemId: string) => {
|
||||||
const updatedItems =
|
const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []
|
||||||
formData.items?.filter((item) => item.id !== itemId) || [];
|
const totals = calculateInvoiceTotals(updatedItems)
|
||||||
const totals = calculateInvoiceTotals(updatedItems);
|
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
items: updatedItems,
|
items: updatedItems,
|
||||||
...totals,
|
...totals,
|
||||||
remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
|
remainingAmount: totals.totalAmount - (prev.paidAmount || 0),
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (!formData.currentAccountId) {
|
if (!formData.currentAccountId) {
|
||||||
alert("Lütfen cari hesap seçin");
|
alert('Lütfen cari hesap seçin')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (!formData.items?.length) {
|
if (!formData.items?.length) {
|
||||||
alert("Lütfen en az bir ürün ekleyin");
|
alert('Lütfen en az bir ürün ekleyin')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
onSave({
|
onSave({
|
||||||
|
|
@ -187,18 +173,18 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
id: invoice?.id || Date.now().toString(),
|
id: invoice?.id || Date.now().toString(),
|
||||||
creationTime: invoice?.creationTime || new Date(),
|
creationTime: invoice?.creationTime || new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const formatCurrency = (amount: number) => {
|
const formatCurrency = (amount: number) => {
|
||||||
return amount.toLocaleString("tr-TR", {
|
return amount.toLocaleString('tr-TR', {
|
||||||
style: "currency",
|
style: 'currency',
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
|
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
|
||||||
|
|
@ -208,7 +194,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<FaFileAlt className="w-5 h-5 text-blue-600" />
|
<FaFileAlt className="w-5 h-5 text-blue-600" />
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{invoice ? "Fatura Düzenle" : "Yeni Fatura"}
|
{invoice ? 'Fatura Düzenle' : 'Yeni Fatura'}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -224,24 +210,18 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
{/* Basic Information */}
|
{/* Basic Information */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Fatura No</label>
|
||||||
Fatura No
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.invoiceNumber}
|
value={formData.invoiceNumber}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, invoiceNumber: e.target.value })}
|
||||||
setFormData({ ...formData, invoiceNumber: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Fatura Türü</label>
|
||||||
Fatura Türü
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.invoiceType}
|
value={formData.invoiceType}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
|
@ -252,36 +232,29 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={InvoiceTypeEnum.Sales}>Satış</option>
|
{Object.values(InvoiceTypeEnum).map((type) => (
|
||||||
<option value={InvoiceTypeEnum.Purchase}>Alış</option>
|
<option key={type} value={type}>
|
||||||
<option value={InvoiceTypeEnum.Return}>İade</option>
|
{getInvoiceTypeText(type)}
|
||||||
<option value={InvoiceTypeEnum.Proforma}>Proforma</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye No</label>
|
||||||
İrsaliye No
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.waybillNumber || ""}
|
value={formData.waybillNumber || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, waybillNumber: e.target.value })}
|
||||||
setFormData({ ...formData, waybillNumber: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Cari Hesap</label>
|
||||||
Cari Hesap
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currentAccountId}
|
value={formData.currentAccountId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, currentAccountId: e.target.value })}
|
||||||
setFormData({ ...formData, currentAccountId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
|
|
@ -295,12 +268,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Fatura Tarihi</label>
|
||||||
Fatura Tarihi
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.invoiceDate?.toISOString().split("T")[0]}
|
value={formData.invoiceDate?.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -313,12 +284,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Vade Tarihi</label>
|
||||||
Vade Tarihi
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.dueDate?.toISOString().split("T")[0]}
|
value={formData.dueDate?.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -333,9 +302,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
|
|
||||||
{/* Invoice Items */}
|
{/* Invoice Items */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">Fatura Kalemleri</h3>
|
||||||
Fatura Kalemleri
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{/* Add New Item */}
|
{/* Add New Item */}
|
||||||
<div className="bg-gray-50 p-3 rounded-lg mb-3">
|
<div className="bg-gray-50 p-3 rounded-lg mb-3">
|
||||||
|
|
@ -346,21 +313,17 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={newItem.description || ""}
|
value={newItem.description || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
|
||||||
setNewItem({ ...newItem, description: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Ürün/Hizmet açıklaması"
|
placeholder="Ürün/Hizmet açıklaması"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Miktar</label>
|
||||||
Miktar
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={newItem.quantity || ""}
|
value={newItem.quantity || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewItem({
|
setNewItem({
|
||||||
...newItem,
|
...newItem,
|
||||||
|
|
@ -378,7 +341,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={newItem.unitPrice || ""}
|
value={newItem.unitPrice || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewItem({
|
setNewItem({
|
||||||
...newItem,
|
...newItem,
|
||||||
|
|
@ -391,11 +354,9 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">KDV (%)</label>
|
||||||
KDV (%)
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={newItem.taxRate || 18}
|
value={newItem.taxRate || 20}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewItem({
|
setNewItem({
|
||||||
...newItem,
|
...newItem,
|
||||||
|
|
@ -408,6 +369,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
<option value={1}>1%</option>
|
<option value={1}>1%</option>
|
||||||
<option value={8}>8%</option>
|
<option value={8}>8%</option>
|
||||||
<option value={18}>18%</option>
|
<option value={18}>18%</option>
|
||||||
|
<option value={20}>20%</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-end">
|
<div className="flex items-end">
|
||||||
|
|
@ -452,18 +414,14 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
<tbody className="divide-y divide-gray-200">
|
<tbody className="divide-y divide-gray-200">
|
||||||
{formData.items.map((item) => (
|
{formData.items.map((item) => (
|
||||||
<tr key={item.id} className="text-sm">
|
<tr key={item.id} className="text-sm">
|
||||||
<td className="px-3 py-2 text-gray-900">
|
<td className="px-3 py-2 text-gray-900">{item.description}</td>
|
||||||
{item.description}
|
|
||||||
</td>
|
|
||||||
<td className="px-3 py-2 text-gray-900 text-right">
|
<td className="px-3 py-2 text-gray-900 text-right">
|
||||||
{item.quantity.toLocaleString("tr-TR")}
|
{item.quantity.toLocaleString('tr-TR')}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-2 text-gray-900 text-right">
|
<td className="px-3 py-2 text-gray-900 text-right">
|
||||||
{formatCurrency(item.unitPrice)}
|
{formatCurrency(item.unitPrice)}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-2 text-gray-900 text-right">
|
<td className="px-3 py-2 text-gray-900 text-right">%{item.taxRate}</td>
|
||||||
%{item.taxRate}
|
|
||||||
</td>
|
|
||||||
<td className="px-3 py-2 text-gray-900 text-right font-medium">
|
<td className="px-3 py-2 text-gray-900 text-right font-medium">
|
||||||
{formatCurrency(item.lineTotal)}
|
{formatCurrency(item.lineTotal)}
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -488,14 +446,10 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
<div className="bg-gray-50 p-4 rounded-lg mb-4">
|
<div className="bg-gray-50 p-4 rounded-lg mb-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Notlar</label>
|
||||||
Notlar
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.notes || ""}
|
value={formData.notes || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
|
||||||
setFormData({ ...formData, notes: e.target.value })
|
|
||||||
}
|
|
||||||
rows={4}
|
rows={4}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Fatura ile ilgili notlar..."
|
placeholder="Fatura ile ilgili notlar..."
|
||||||
|
|
@ -504,9 +458,7 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-600">Ara Toplam:</span>
|
<span className="text-sm text-gray-600">Ara Toplam:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{formatCurrency(formData.subtotal || 0)}</span>
|
||||||
{formatCurrency(formData.subtotal || 0)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-600">İndirim:</span>
|
<span className="text-sm text-gray-600">İndirim:</span>
|
||||||
|
|
@ -516,15 +468,11 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-600">KDV:</span>
|
<span className="text-sm text-gray-600">KDV:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{formatCurrency(formData.taxAmount || 0)}</span>
|
||||||
{formatCurrency(formData.taxAmount || 0)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t pt-3">
|
<div className="border-t pt-3">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-base font-semibold text-gray-900">
|
<span className="text-base font-semibold text-gray-900">Genel Toplam:</span>
|
||||||
Genel Toplam:
|
|
||||||
</span>
|
|
||||||
<span className="text-base font-bold text-blue-600">
|
<span className="text-base font-bold text-blue-600">
|
||||||
{formatCurrency(formData.totalAmount || 0)}
|
{formatCurrency(formData.totalAmount || 0)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -548,13 +496,13 @@ const InvoiceForm: React.FC<InvoiceFormProps> = ({
|
||||||
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2"
|
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{invoice ? "Güncelle" : "Kaydet"}
|
{invoice ? 'Güncelle' : 'Kaydet'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default InvoiceForm;
|
export default InvoiceForm
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from 'react'
|
||||||
import {
|
import {
|
||||||
FaPlus,
|
FaPlus,
|
||||||
FaSearch,
|
FaSearch,
|
||||||
|
|
@ -8,15 +8,10 @@ import {
|
||||||
FaFileAlt,
|
FaFileAlt,
|
||||||
FaEdit,
|
FaEdit,
|
||||||
FaSave,
|
FaSave,
|
||||||
} from "react-icons/fa";
|
} from 'react-icons/fa'
|
||||||
import {
|
import { FiInvoice, InvoiceTypeEnum, InvoiceStatusEnum, PaymentStatusEnum } from '../../../types/fi'
|
||||||
FiInvoice,
|
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||||
InvoiceTypeEnum,
|
import Widget from '../../../components/common/Widget'
|
||||||
InvoiceStatusEnum,
|
|
||||||
PaymentStatusEnum,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
import DataTable, { Column } from "../../../components/common/DataTable";
|
|
||||||
import Widget from "../../../components/common/Widget";
|
|
||||||
import {
|
import {
|
||||||
getInvoiceTypeColor,
|
getInvoiceTypeColor,
|
||||||
getInvoiceTypeText,
|
getInvoiceTypeText,
|
||||||
|
|
@ -24,15 +19,15 @@ import {
|
||||||
getInvoiceStatusText,
|
getInvoiceStatusText,
|
||||||
getPaymentStatusColor,
|
getPaymentStatusColor,
|
||||||
getPaymentStatusText,
|
getPaymentStatusText,
|
||||||
} from "../../../utils/erp";
|
} from '../../../utils/erp'
|
||||||
|
|
||||||
interface InvoiceManagementProps {
|
interface InvoiceManagementProps {
|
||||||
invoices: FiInvoice[];
|
invoices: FiInvoice[]
|
||||||
onAdd: () => void;
|
onAdd: () => void
|
||||||
onEdit: (invoice: FiInvoice) => void;
|
onEdit: (invoice: FiInvoice) => void
|
||||||
onConvertFromWaybill: () => void;
|
onConvertFromWaybill: () => void
|
||||||
onCreatePayment: (invoice: FiInvoice) => void;
|
onCreatePayment: (invoice: FiInvoice) => void
|
||||||
onViewDetails: (invoice: FiInvoice) => void;
|
onViewDetails: (invoice: FiInvoice) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
|
|
@ -43,103 +38,85 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
onCreatePayment,
|
onCreatePayment,
|
||||||
onViewDetails,
|
onViewDetails,
|
||||||
}) => {
|
}) => {
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [selectedType, setSelectedType] = useState<InvoiceTypeEnum | "all">(
|
const [selectedType, setSelectedType] = useState<InvoiceTypeEnum | 'all'>('all')
|
||||||
"all"
|
const [selectedStatus, setSelectedStatus] = useState<InvoiceStatusEnum | 'all'>('all')
|
||||||
);
|
const [selectedPaymentStatus, setSelectedPaymentStatus] = useState<PaymentStatusEnum | 'all'>(
|
||||||
const [selectedStatus, setSelectedStatus] = useState<
|
'all',
|
||||||
InvoiceStatusEnum | "all"
|
)
|
||||||
>("all");
|
const [sortBy, setSortBy] = useState<'date' | 'amount' | 'dueDate'>('date')
|
||||||
const [selectedPaymentStatus, setSelectedPaymentStatus] = useState<
|
|
||||||
PaymentStatusEnum | "all"
|
|
||||||
>("all");
|
|
||||||
const [sortBy, setSortBy] = useState<"date" | "amount" | "dueDate">("date");
|
|
||||||
|
|
||||||
const filteredInvoices = invoices
|
const filteredInvoices = invoices
|
||||||
.filter((invoice) => {
|
.filter((invoice) => {
|
||||||
if (
|
if (
|
||||||
searchTerm &&
|
searchTerm &&
|
||||||
!invoice.invoiceNumber
|
!invoice.invoiceNumber.toLowerCase().includes(searchTerm.toLowerCase()) &&
|
||||||
.toLowerCase()
|
!invoice.currentAccount?.accountCode?.toLowerCase().includes(searchTerm.toLowerCase()) &&
|
||||||
.includes(searchTerm.toLowerCase()) &&
|
|
||||||
!invoice.currentAccount?.accountCode
|
|
||||||
?.toLowerCase()
|
|
||||||
.includes(searchTerm.toLowerCase()) &&
|
|
||||||
!invoice.waybillNumber?.toLowerCase().includes(searchTerm.toLowerCase())
|
!invoice.waybillNumber?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
) {
|
) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (selectedType !== "all" && invoice.invoiceType !== selectedType) {
|
if (selectedType !== 'all' && invoice.invoiceType !== selectedType) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (selectedStatus !== "all" && invoice.status !== selectedStatus) {
|
if (selectedStatus !== 'all' && invoice.status !== selectedStatus) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (
|
if (selectedPaymentStatus !== 'all' && invoice.paymentStatus !== selectedPaymentStatus) {
|
||||||
selectedPaymentStatus !== "all" &&
|
return false
|
||||||
invoice.paymentStatus !== selectedPaymentStatus
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
switch (sortBy) {
|
switch (sortBy) {
|
||||||
case "date":
|
case 'date':
|
||||||
return (
|
return new Date(b.invoiceDate).getTime() - new Date(a.invoiceDate).getTime()
|
||||||
new Date(b.invoiceDate).getTime() -
|
case 'amount':
|
||||||
new Date(a.invoiceDate).getTime()
|
return b.totalAmount - a.totalAmount
|
||||||
);
|
case 'dueDate':
|
||||||
case "amount":
|
return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime()
|
||||||
return b.totalAmount - a.totalAmount;
|
|
||||||
case "dueDate":
|
|
||||||
return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime();
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getDaysUntilDue = (dueDate: Date) => {
|
const getDaysUntilDue = (dueDate: Date) => {
|
||||||
const today = new Date();
|
const today = new Date()
|
||||||
const due = new Date(dueDate);
|
const due = new Date(dueDate)
|
||||||
const diffTime = due.getTime() - today.getTime();
|
const diffTime = due.getTime() - today.getTime()
|
||||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||||
return diffDays;
|
return diffDays
|
||||||
};
|
}
|
||||||
|
|
||||||
const formatCurrency = (amount: number) => {
|
const formatCurrency = (amount: number) => {
|
||||||
return amount.toLocaleString("tr-TR", {
|
return amount.toLocaleString('tr-TR', {
|
||||||
style: "currency",
|
style: 'currency',
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const columns: Column<FiInvoice>[] = [
|
const columns: Column<FiInvoice>[] = [
|
||||||
{
|
{
|
||||||
key: "invoiceNumber",
|
key: 'invoiceNumber',
|
||||||
header: "Fatura No",
|
header: 'Fatura No',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
render: (invoice: FiInvoice) => (
|
render: (invoice: FiInvoice) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">{invoice.invoiceNumber}</div>
|
||||||
{invoice.invoiceNumber}
|
|
||||||
</div>
|
|
||||||
{invoice.waybillNumber && (
|
{invoice.waybillNumber && (
|
||||||
<div className="text-sm text-gray-500">
|
<div className="text-sm text-gray-500">İrs: {invoice.waybillNumber}</div>
|
||||||
İrs: {invoice.waybillNumber}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "type",
|
key: 'type',
|
||||||
header: "Tür",
|
header: 'Tür',
|
||||||
render: (invoice: FiInvoice) => (
|
render: (invoice: FiInvoice) => (
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
|
||||||
invoice.invoiceType
|
invoice.invoiceType,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getInvoiceTypeText(invoice.invoiceType)}
|
{getInvoiceTypeText(invoice.invoiceType)}
|
||||||
|
|
@ -147,61 +124,54 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "currentAccount",
|
key: 'currentAccount',
|
||||||
header: "Cari Hesap",
|
header: 'Cari Hesap',
|
||||||
render: (invoice: FiInvoice) => (
|
render: (invoice: FiInvoice) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">
|
||||||
{invoice.currentAccount?.accountCode || "Bilinmeyen"}
|
{invoice.currentAccount?.accountCode || 'Bilinmeyen'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "dates",
|
key: 'dates',
|
||||||
header: "Tarihler",
|
header: 'Tarihler',
|
||||||
render: (invoice: FiInvoice) => {
|
render: (invoice: FiInvoice) => {
|
||||||
const daysUntilDue = getDaysUntilDue(invoice.dueDate);
|
const daysUntilDue = getDaysUntilDue(invoice.dueDate)
|
||||||
return (
|
return (
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<FaCalendar className="w-3 h-3 text-gray-400" />
|
<FaCalendar className="w-3 h-3 text-gray-400" />
|
||||||
<span>
|
<span>Fatura: {new Date(invoice.invoiceDate).toLocaleDateString('tr-TR')}</span>
|
||||||
Fatura:{" "}
|
|
||||||
{new Date(invoice.invoiceDate).toLocaleDateString("tr-TR")}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<FaClock className="w-3 h-3 text-gray-400" />
|
<FaClock className="w-3 h-3 text-gray-400" />
|
||||||
<span
|
<span
|
||||||
className={
|
className={
|
||||||
daysUntilDue < 0
|
daysUntilDue < 0
|
||||||
? "text-red-600"
|
? 'text-red-600'
|
||||||
: daysUntilDue <= 7
|
: daysUntilDue <= 7
|
||||||
? "text-orange-600"
|
? 'text-orange-600'
|
||||||
: "text-gray-600"
|
: 'text-gray-600'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Vade: {new Date(invoice.dueDate).toLocaleDateString("tr-TR")}
|
Vade: {new Date(invoice.dueDate).toLocaleDateString('tr-TR')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{daysUntilDue < 0 && (
|
{daysUntilDue < 0 && (
|
||||||
<div className="text-xs text-red-600">
|
<div className="text-xs text-red-600">{Math.abs(daysUntilDue)} gün gecikme</div>
|
||||||
{Math.abs(daysUntilDue)} gün gecikme
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "amounts",
|
key: 'amounts',
|
||||||
header: "Tutarlar",
|
header: 'Tutarlar',
|
||||||
render: (invoice: FiInvoice) => (
|
render: (invoice: FiInvoice) => (
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">{formatCurrency(invoice.totalAmount)}</div>
|
||||||
{formatCurrency(invoice.totalAmount)}
|
|
||||||
</div>
|
|
||||||
{invoice.paidAmount > 0 && (
|
{invoice.paidAmount > 0 && (
|
||||||
<div className="text-sm text-green-600">
|
<div className="text-sm text-green-600">
|
||||||
Ödenen: {formatCurrency(invoice.paidAmount)}
|
Ödenen: {formatCurrency(invoice.paidAmount)}
|
||||||
|
|
@ -216,13 +186,13 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "status",
|
key: 'status',
|
||||||
header: "Durum",
|
header: 'Durum',
|
||||||
render: (invoice: FiInvoice) => (
|
render: (invoice: FiInvoice) => (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceStatusColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceStatusColor(
|
||||||
invoice.status
|
invoice.status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getInvoiceStatusText(invoice.status)}
|
{getInvoiceStatusText(invoice.status)}
|
||||||
|
|
@ -230,7 +200,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
<br />
|
<br />
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
|
||||||
invoice.paymentStatus
|
invoice.paymentStatus,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getPaymentStatusText(invoice.paymentStatus)}
|
{getPaymentStatusText(invoice.paymentStatus)}
|
||||||
|
|
@ -239,8 +209,8 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "actions",
|
key: 'actions',
|
||||||
header: "İşlemler",
|
header: 'İşlemler',
|
||||||
render: (invoice: FiInvoice) => (
|
render: (invoice: FiInvoice) => (
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
{invoice.paymentStatus !== PaymentStatusEnum.Paid && (
|
{invoice.paymentStatus !== PaymentStatusEnum.Paid && (
|
||||||
|
|
@ -269,37 +239,33 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
||||||
// Calculate statistics
|
// Calculate statistics
|
||||||
const totalInvoices = invoices.length;
|
const totalInvoices = invoices.length
|
||||||
const totalSalesAmount = invoices
|
const totalSalesAmount = invoices
|
||||||
.filter((i) => i.invoiceType === InvoiceTypeEnum.Sales)
|
.filter((i) => i.invoiceType === InvoiceTypeEnum.Sales)
|
||||||
.reduce((sum, i) => sum + i.totalAmount, 0);
|
.reduce((sum, i) => sum + i.totalAmount, 0)
|
||||||
const totalPurchaseAmount = invoices
|
const totalPurchaseAmount = invoices
|
||||||
.filter((i) => i.invoiceType === InvoiceTypeEnum.Purchase)
|
.filter((i) => i.invoiceType === InvoiceTypeEnum.Purchase)
|
||||||
.reduce((sum, i) => sum + i.totalAmount, 0);
|
.reduce((sum, i) => sum + i.totalAmount, 0)
|
||||||
const totalUnpaidAmount = invoices
|
const totalUnpaidAmount = invoices
|
||||||
.filter((i) => i.paymentStatus !== PaymentStatusEnum.Paid)
|
.filter((i) => i.paymentStatus !== PaymentStatusEnum.Paid)
|
||||||
.reduce((sum, i) => sum + i.remainingAmount, 0);
|
.reduce((sum, i) => sum + i.remainingAmount, 0)
|
||||||
|
|
||||||
// Overdue invoices
|
// Overdue invoices
|
||||||
const overdueInvoices = invoices.filter(
|
const overdueInvoices = invoices.filter(
|
||||||
(i) =>
|
(i) => i.paymentStatus !== PaymentStatusEnum.Paid && new Date(i.dueDate) < new Date(),
|
||||||
i.paymentStatus !== PaymentStatusEnum.Paid &&
|
)
|
||||||
new Date(i.dueDate) < new Date()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Payment status distribution
|
// Payment status distribution
|
||||||
const paymentDistribution = Object.values(PaymentStatusEnum).map(
|
const paymentDistribution = Object.values(PaymentStatusEnum).map((status) => ({
|
||||||
(status) => ({
|
status,
|
||||||
status,
|
count: invoices.filter((i) => i.paymentStatus === status).length,
|
||||||
count: invoices.filter((i) => i.paymentStatus === status).length,
|
amount: invoices
|
||||||
amount: invoices
|
.filter((i) => i.paymentStatus === status)
|
||||||
.filter((i) => i.paymentStatus === status)
|
.reduce((sum, i) => sum + i.totalAmount, 0),
|
||||||
.reduce((sum, i) => sum + i.totalAmount, 0),
|
}))
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Invoice type distribution
|
// Invoice type distribution
|
||||||
const typeDistribution = Object.values(InvoiceTypeEnum).map((type) => ({
|
const typeDistribution = Object.values(InvoiceTypeEnum).map((type) => ({
|
||||||
|
|
@ -308,7 +274,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
amount: invoices
|
amount: invoices
|
||||||
.filter((i) => i.invoiceType === type)
|
.filter((i) => i.invoiceType === type)
|
||||||
.reduce((sum, i) => sum + i.totalAmount, 0),
|
.reduce((sum, i) => sum + i.totalAmount, 0),
|
||||||
}));
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|
@ -316,9 +282,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Fatura Yönetimi</h2>
|
<h2 className="text-2xl font-bold text-gray-900">Fatura Yönetimi</h2>
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600">Alış ve satış faturaları yönetimi</p>
|
||||||
Alış ve satış faturaları yönetimi
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 text-sm">
|
<div className="flex gap-2 text-sm">
|
||||||
<button
|
<button
|
||||||
|
|
@ -340,12 +304,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
|
|
||||||
{/* Stats Cards */}
|
{/* Stats Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||||
<Widget
|
<Widget title="Toplam Fatura" value={totalInvoices} color="blue" icon="FaFileAlt" />
|
||||||
title="Toplam Fatura"
|
|
||||||
value={totalInvoices}
|
|
||||||
color="blue"
|
|
||||||
icon="FaFileAlt"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Widget
|
<Widget
|
||||||
title="Satış Tutarı"
|
title="Satış Tutarı"
|
||||||
|
|
@ -372,16 +331,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
{/* Distribution Charts */}
|
{/* Distribution Charts */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">Fatura Türü Dağılımı</h3>
|
||||||
Fatura Türü Dağılımı
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{typeDistribution.map(({ type, count, amount }) => (
|
{typeDistribution.map(({ type, count, amount }) => (
|
||||||
<div key={type} className="flex items-center justify-between">
|
<div key={type} className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getInvoiceTypeColor(
|
||||||
type
|
type,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getInvoiceTypeText(type)}
|
{getInvoiceTypeText(type)}
|
||||||
|
|
@ -399,16 +356,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">Ödeme Durumu Dağılımı</h3>
|
||||||
Ödeme Durumu Dağılımı
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{paymentDistribution.map(({ status, count, amount }) => (
|
{paymentDistribution.map(({ status, count, amount }) => (
|
||||||
<div key={status} className="flex items-center justify-between">
|
<div key={status} className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getPaymentStatusColor(
|
||||||
status
|
status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getPaymentStatusText(status)}
|
{getPaymentStatusText(status)}
|
||||||
|
|
@ -431,20 +386,15 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
<div className="bg-red-50 border border-red-200 rounded-lg p-3">
|
<div className="bg-red-50 border border-red-200 rounded-lg p-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<FaExclamationTriangle className="w-5 h-5 text-red-600" />
|
<FaExclamationTriangle className="w-5 h-5 text-red-600" />
|
||||||
<h3 className="text-base font-semibold text-red-900">
|
<h3 className="text-base font-semibold text-red-900">Vadesi Geçmiş Faturalar</h3>
|
||||||
Vadesi Geçmiş Faturalar
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-red-700 mt-1">
|
<p className="text-sm text-red-700 mt-1">
|
||||||
{overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam
|
{overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam tutar:{' '}
|
||||||
tutar:{" "}
|
{formatCurrency(overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0))}
|
||||||
{formatCurrency(
|
|
||||||
overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0)
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-2 space-y-1.5">
|
<div className="mt-2 space-y-1.5">
|
||||||
{overdueInvoices.slice(0, 3).map((invoice) => {
|
{overdueInvoices.slice(0, 3).map((invoice) => {
|
||||||
const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate));
|
const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -466,7 +416,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -487,9 +437,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={selectedType}
|
value={selectedType}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSelectedType(e.target.value as InvoiceTypeEnum | 'all')}
|
||||||
setSelectedType(e.target.value as InvoiceTypeEnum | "all")
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Türler</option>
|
<option value="all">Tüm Türler</option>
|
||||||
|
|
@ -502,9 +450,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={selectedStatus}
|
value={selectedStatus}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSelectedStatus(e.target.value as InvoiceStatusEnum | 'all')}
|
||||||
setSelectedStatus(e.target.value as InvoiceStatusEnum | "all")
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
|
|
@ -517,11 +463,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={selectedPaymentStatus}
|
value={selectedPaymentStatus}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSelectedPaymentStatus(e.target.value as PaymentStatusEnum | 'all')}
|
||||||
setSelectedPaymentStatus(
|
|
||||||
e.target.value as PaymentStatusEnum | "all"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Ödeme Durumları</option>
|
<option value="all">Tüm Ödeme Durumları</option>
|
||||||
|
|
@ -534,9 +476,7 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={sortBy}
|
value={sortBy}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSortBy(e.target.value as 'date' | 'amount' | 'dueDate')}
|
||||||
setSortBy(e.target.value as "date" | "amount" | "dueDate")
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="date">Tarihe Göre</option>
|
<option value="date">Tarihe Göre</option>
|
||||||
|
|
@ -553,16 +493,14 @@ const InvoiceManagement: React.FC<InvoiceManagementProps> = ({
|
||||||
{filteredInvoices.length === 0 && (
|
{filteredInvoices.length === 0 && (
|
||||||
<div className="text-center py-10">
|
<div className="text-center py-10">
|
||||||
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
|
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-2">
|
<h3 className="text-base font-medium text-gray-900 mb-2">Fatura bulunamadı</h3>
|
||||||
Fatura bulunamadı
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
Yeni bir fatura ekleyin veya arama kriterlerinizi değiştirin.
|
Yeni bir fatura ekleyin veya arama kriterlerinizi değiştirin.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default InvoiceManagement;
|
export default InvoiceManagement
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaFileAlt, FaSave, FaTimes } from "react-icons/fa";
|
import { FaFileAlt, FaSave, FaTimes } from 'react-icons/fa'
|
||||||
import {
|
import { PromissoryNote, NoteStatusEnum, FiCurrentAccount, TypeEnum } from '../../../types/fi'
|
||||||
PromissoryNote,
|
import { getNoteStatusText, getTypeText } from '@/utils/erp'
|
||||||
NoteTypeEnum,
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
NoteStatusEnum,
|
|
||||||
FiCurrentAccount,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
|
|
||||||
interface PromissoryNoteFormProps {
|
interface PromissoryNoteFormProps {
|
||||||
note?: PromissoryNote;
|
note?: PromissoryNote
|
||||||
currentAccounts: FiCurrentAccount[];
|
currentAccounts: FiCurrentAccount[]
|
||||||
onSave: (
|
onSave: (note: Omit<PromissoryNote, 'id' | 'creationTime' | 'lastModificationTime'>) => void
|
||||||
note: Omit<PromissoryNote, "id" | "creationTime" | "lastModificationTime">
|
onCancel: () => void
|
||||||
) => void;
|
isOpen: boolean
|
||||||
onCancel: () => void;
|
|
||||||
isOpen: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
|
|
@ -25,21 +20,21 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
noteNumber: "",
|
noteNumber: '',
|
||||||
drawerName: "",
|
drawerName: '',
|
||||||
payeeName: "",
|
payeeName: '',
|
||||||
currentAccountId: "",
|
currentAccountId: '',
|
||||||
issueDate: new Date().toISOString().split("T")[0],
|
issueDate: new Date().toISOString().split('T')[0],
|
||||||
dueDate: new Date().toISOString().split("T")[0],
|
dueDate: new Date().toISOString().split('T')[0],
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: NoteStatusEnum.InHand,
|
status: NoteStatusEnum.InHand,
|
||||||
type: NoteTypeEnum.Received,
|
type: TypeEnum.Received,
|
||||||
location: "",
|
location: '',
|
||||||
notes: "",
|
notes: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (note) {
|
if (note) {
|
||||||
|
|
@ -47,60 +42,60 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
noteNumber: note.noteNumber,
|
noteNumber: note.noteNumber,
|
||||||
drawerName: note.drawerName,
|
drawerName: note.drawerName,
|
||||||
payeeName: note.payeeName,
|
payeeName: note.payeeName,
|
||||||
currentAccountId: note.currentAccountId || "",
|
currentAccountId: note.currentAccountId || '',
|
||||||
issueDate: new Date(note.issueDate).toISOString().split("T")[0],
|
issueDate: new Date(note.issueDate).toISOString().split('T')[0],
|
||||||
dueDate: new Date(note.dueDate).toISOString().split("T")[0],
|
dueDate: new Date(note.dueDate).toISOString().split('T')[0],
|
||||||
amount: note.amount,
|
amount: note.amount,
|
||||||
currency: note.currency,
|
currency: note.currency,
|
||||||
status: note.status,
|
status: note.status,
|
||||||
type: note.type,
|
type: note.type,
|
||||||
location: note.location || "",
|
location: note.location || '',
|
||||||
notes: note.notes || "",
|
notes: note.notes || '',
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
noteNumber: "",
|
noteNumber: '',
|
||||||
drawerName: "",
|
drawerName: '',
|
||||||
payeeName: "",
|
payeeName: '',
|
||||||
currentAccountId: "",
|
currentAccountId: '',
|
||||||
issueDate: new Date().toISOString().split("T")[0],
|
issueDate: new Date().toISOString().split('T')[0],
|
||||||
dueDate: new Date().toISOString().split("T")[0],
|
dueDate: new Date().toISOString().split('T')[0],
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: NoteStatusEnum.InHand,
|
status: NoteStatusEnum.InHand,
|
||||||
type: NoteTypeEnum.Received,
|
type: TypeEnum.Received,
|
||||||
location: "",
|
location: '',
|
||||||
notes: "",
|
notes: '',
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setErrors({});
|
setErrors({})
|
||||||
}, [note, isOpen]);
|
}, [note, isOpen])
|
||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const newErrors: Record<string, string> = {};
|
const newErrors: Record<string, string> = {}
|
||||||
|
|
||||||
if (!formData.noteNumber.trim()) {
|
if (!formData.noteNumber.trim()) {
|
||||||
newErrors.noteNumber = "Senet numarası gereklidir";
|
newErrors.noteNumber = 'Senet numarası gereklidir'
|
||||||
}
|
}
|
||||||
if (!formData.drawerName.trim()) {
|
if (!formData.drawerName.trim()) {
|
||||||
newErrors.drawerName = "Keşideci adı gereklidir";
|
newErrors.drawerName = 'Keşideci adı gereklidir'
|
||||||
}
|
}
|
||||||
if (!formData.payeeName.trim()) {
|
if (!formData.payeeName.trim()) {
|
||||||
newErrors.payeeName = "Lehtar adı gereklidir";
|
newErrors.payeeName = 'Lehtar adı gereklidir'
|
||||||
}
|
}
|
||||||
if (formData.amount <= 0) {
|
if (formData.amount <= 0) {
|
||||||
newErrors.amount = "Tutar 0'dan büyük olmalıdır";
|
newErrors.amount = "Tutar 0'dan büyük olmalıdır"
|
||||||
}
|
}
|
||||||
if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
|
if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
|
||||||
newErrors.dueDate = "Vade tarihi düzenleme tarihinden sonra olmalıdır";
|
newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors)
|
||||||
return Object.keys(newErrors).length === 0;
|
return Object.keys(newErrors).length === 0
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
const noteData = {
|
const noteData = {
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -109,22 +104,19 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
currentAccount: formData.currentAccountId
|
currentAccount: formData.currentAccountId
|
||||||
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
|
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
}
|
||||||
onSave(noteData);
|
onSave(noteData)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (field: string, value: string | number | TypeEnum | NoteStatusEnum) => {
|
||||||
field: string,
|
setFormData((prev) => ({ ...prev, [field]: value }))
|
||||||
value: string | number | NoteTypeEnum | NoteStatusEnum
|
|
||||||
) => {
|
|
||||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
||||||
if (errors[field]) {
|
if (errors[field]) {
|
||||||
setErrors((prev) => ({ ...prev, [field]: "" }));
|
setErrors((prev) => ({ ...prev, [field]: '' }))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
|
@ -133,13 +125,10 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<FaFileAlt className="w-5 h-5 text-green-600" />
|
<FaFileAlt className="w-5 h-5 text-green-600" />
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{note ? "Senet Düzenle" : "Yeni Senet"}
|
{note ? 'Senet Düzenle' : 'Yeni Senet'}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
|
||||||
onClick={onCancel}
|
|
||||||
className="p-2 hover:bg-gray-100 rounded-md"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5 text-gray-500" />
|
<FaTimes className="w-5 h-5 text-gray-500" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -154,11 +143,9 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.noteNumber}
|
value={formData.noteNumber}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('noteNumber', e.target.value)}
|
||||||
handleInputChange("noteNumber", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
||||||
errors.noteNumber ? "border-red-500" : "border-gray-300"
|
errors.noteNumber ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Senet numarasını giriniz"
|
placeholder="Senet numarasını giriniz"
|
||||||
/>
|
/>
|
||||||
|
|
@ -168,100 +155,77 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
|
||||||
Tür *
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.type}
|
value={formData.type}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
|
||||||
handleInputChange("type", e.target.value as NoteTypeEnum)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
>
|
>
|
||||||
<option value={NoteTypeEnum.Received}>Alınan Senet</option>
|
{Object.values(TypeEnum).map((type) => (
|
||||||
<option value={NoteTypeEnum.Issued}>Verilen Senet</option>
|
<option key={type} value={type}>
|
||||||
|
{getTypeText(type)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||||
Durum
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.status}
|
value={formData.status}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('status', e.target.value as NoteStatusEnum)}
|
||||||
handleInputChange("status", e.target.value as NoteStatusEnum)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
>
|
>
|
||||||
<option value={NoteStatusEnum.InHand}>Elde</option>
|
{Object.values(NoteStatusEnum).map((status) => (
|
||||||
<option value={NoteStatusEnum.Collected}>Tahsil Edildi</option>
|
<option key={status} value={status}>
|
||||||
<option value={NoteStatusEnum.Overdue}>Vadesi Geçmiş</option>
|
{getNoteStatusText(status)}
|
||||||
<option value={NoteStatusEnum.Endorsed}>Ciro Edildi</option>
|
</option>
|
||||||
<option value={NoteStatusEnum.Cancelled}>İptal</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Taraf Bilgileri */}
|
{/* Taraf Bilgileri */}
|
||||||
<div className="bg-gray-50 p-3 rounded-lg">
|
<div className="bg-gray-50 p-3 rounded-lg">
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-3">
|
<h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
|
||||||
Taraf Bilgileri
|
|
||||||
</h3>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
|
||||||
Keşideci *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.drawerName}
|
value={formData.drawerName}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('drawerName', e.target.value)}
|
||||||
handleInputChange("drawerName", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
||||||
errors.drawerName ? "border-red-500" : "border-gray-300"
|
errors.drawerName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Keşideci adını giriniz"
|
placeholder="Keşideci adını giriniz"
|
||||||
/>
|
/>
|
||||||
{errors.drawerName && (
|
{errors.drawerName && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
|
||||||
{errors.drawerName}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
|
||||||
Lehtar *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.payeeName}
|
value={formData.payeeName}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('payeeName', e.target.value)}
|
||||||
handleInputChange("payeeName", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
||||||
errors.payeeName ? "border-red-500" : "border-gray-300"
|
errors.payeeName ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Lehtar adını giriniz"
|
placeholder="Lehtar adını giriniz"
|
||||||
/>
|
/>
|
||||||
{errors.payeeName && (
|
{errors.payeeName && (
|
||||||
<p className="text-red-500 text-xs mt-1">
|
<p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
|
||||||
{errors.payeeName}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
|
||||||
Cari Hesap
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currentAccountId}
|
value={formData.currentAccountId}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('currentAccountId', e.target.value)}
|
||||||
handleInputChange("currentAccountId", e.target.value)
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
>
|
>
|
||||||
<option value="">Cari hesap seçiniz</option>
|
<option value="">Cari hesap seçiniz</option>
|
||||||
|
|
@ -278,39 +242,33 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
{/* Tutar ve Tarih Bilgileri */}
|
{/* Tutar ve Tarih Bilgileri */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
|
||||||
Tutar *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
min="0"
|
min="0"
|
||||||
value={formData.amount}
|
value={formData.amount}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('amount', parseFloat(e.target.value) || 0)}
|
||||||
handleInputChange("amount", parseFloat(e.target.value) || 0)
|
|
||||||
}
|
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
||||||
errors.amount ? "border-red-500" : "border-gray-300"
|
errors.amount ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="0.00"
|
placeholder="0.00"
|
||||||
/>
|
/>
|
||||||
{errors.amount && (
|
{errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.amount}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||||
Para Birimi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currency}
|
value={formData.currency}
|
||||||
onChange={(e) => handleInputChange("currency", e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -321,38 +279,32 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.issueDate}
|
value={formData.issueDate}
|
||||||
onChange={(e) => handleInputChange("issueDate", e.target.value)}
|
onChange={(e) => handleInputChange('issueDate', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
|
||||||
Vade Tarihi *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.dueDate}
|
value={formData.dueDate}
|
||||||
onChange={(e) => handleInputChange("dueDate", e.target.value)}
|
onChange={(e) => handleInputChange('dueDate', e.target.value)}
|
||||||
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 ${
|
||||||
errors.dueDate ? "border-red-500" : "border-gray-300"
|
errors.dueDate ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
{errors.dueDate && (
|
{errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
|
||||||
<p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Konum */}
|
{/* Konum */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Konum</label>
|
||||||
Konum
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.location}
|
value={formData.location}
|
||||||
onChange={(e) => handleInputChange("location", e.target.value)}
|
onChange={(e) => handleInputChange('location', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
placeholder="Senetin bulunduğu konum"
|
placeholder="Senetin bulunduğu konum"
|
||||||
/>
|
/>
|
||||||
|
|
@ -360,12 +312,10 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
|
|
||||||
{/* Notlar */}
|
{/* Notlar */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
|
||||||
Notlar
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.notes}
|
value={formData.notes}
|
||||||
onChange={(e) => handleInputChange("notes", e.target.value)}
|
onChange={(e) => handleInputChange('notes', e.target.value)}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
|
||||||
placeholder="Ek notlar..."
|
placeholder="Ek notlar..."
|
||||||
|
|
@ -386,13 +336,13 @@ const PromissoryNoteForm: React.FC<PromissoryNoteFormProps> = ({
|
||||||
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors"
|
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{note ? "Güncelle" : "Kaydet"}
|
{note ? 'Güncelle' : 'Kaydet'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default PromissoryNoteForm;
|
export default PromissoryNoteForm
|
||||||
|
|
|
||||||
|
|
@ -1,178 +1,161 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaSave, FaTimes, FaPlus, FaTrash, FaTruck } from "react-icons/fa";
|
import { FaSave, FaTimes, FaPlus, FaTrash, FaTruck } from 'react-icons/fa'
|
||||||
import {
|
import { FiWaybill, FiWaybillItem, WaybillTypeEnum, WaybillStatusEnum } from '../../../types/fi'
|
||||||
FiWaybill,
|
import { mockCurrentAccounts } from '../../../mocks/mockCurrentAccounts'
|
||||||
FiWaybillItem,
|
import { getWaybillStatusText, getWaybillTypeText } from '@/utils/erp'
|
||||||
WaybillTypeEnum,
|
|
||||||
WaybillStatusEnum,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
import { mockCurrentAccounts } from "../../../mocks/mockCurrentAccounts";
|
|
||||||
|
|
||||||
interface WaybillFormProps {
|
interface WaybillFormProps {
|
||||||
waybill?: FiWaybill;
|
waybill?: FiWaybill
|
||||||
onSave: (waybill: Partial<FiWaybill>) => void;
|
onSave: (waybill: Partial<FiWaybill>) => void
|
||||||
onCancel: () => void;
|
onCancel: () => void
|
||||||
isVisible: boolean;
|
isVisible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const WaybillForm: React.FC<WaybillFormProps> = ({
|
const WaybillForm: React.FC<WaybillFormProps> = ({ waybill, onSave, onCancel, isVisible }) => {
|
||||||
waybill,
|
|
||||||
onSave,
|
|
||||||
onCancel,
|
|
||||||
isVisible,
|
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState<Partial<FiWaybill>>({
|
const [formData, setFormData] = useState<Partial<FiWaybill>>({
|
||||||
waybillNumber: "",
|
waybillNumber: '',
|
||||||
waybillType: WaybillTypeEnum.Outgoing,
|
waybillType: WaybillTypeEnum.Outgoing,
|
||||||
currentAccountId: "",
|
currentAccountId: '',
|
||||||
waybillDate: new Date(),
|
waybillDate: new Date(),
|
||||||
deliveryDate: new Date(),
|
deliveryDate: new Date(),
|
||||||
subtotal: 0,
|
subtotal: 0,
|
||||||
taxAmount: 0,
|
taxAmount: 0,
|
||||||
discountAmount: 0,
|
discountAmount: 0,
|
||||||
totalAmount: 0,
|
totalAmount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
status: WaybillStatusEnum.Draft,
|
status: WaybillStatusEnum.Draft,
|
||||||
isInvoiced: false,
|
isInvoiced: false,
|
||||||
items: [],
|
items: [],
|
||||||
deliveryAddress: "",
|
deliveryAddress: '',
|
||||||
receiverName: "",
|
receiverName: '',
|
||||||
receiverPhone: "",
|
receiverPhone: '',
|
||||||
carrierCompany: "",
|
carrierCompany: '',
|
||||||
trackingNumber: "",
|
trackingNumber: '',
|
||||||
notes: "",
|
notes: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
const [newItem, setNewItem] = useState<Partial<FiWaybillItem>>({
|
const [newItem, setNewItem] = useState<Partial<FiWaybillItem>>({
|
||||||
description: "",
|
description: '',
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
unitPrice: 0,
|
unitPrice: 0,
|
||||||
taxRate: 18,
|
taxRate: 18,
|
||||||
discountRate: 0,
|
discountRate: 0,
|
||||||
unit: "Adet",
|
unit: 'Adet',
|
||||||
});
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (waybill) {
|
if (waybill) {
|
||||||
setFormData({
|
setFormData({
|
||||||
...waybill,
|
...waybill,
|
||||||
waybillDate: new Date(waybill.waybillDate),
|
waybillDate: new Date(waybill.waybillDate),
|
||||||
deliveryDate: waybill.deliveryDate
|
deliveryDate: waybill.deliveryDate ? new Date(waybill.deliveryDate) : new Date(),
|
||||||
? new Date(waybill.deliveryDate)
|
})
|
||||||
: new Date(),
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// Generate new waybill number
|
// Generate new waybill number
|
||||||
const now = new Date();
|
const now = new Date()
|
||||||
const year = now.getFullYear();
|
const year = now.getFullYear()
|
||||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||||
const waybillNumber = `IRS${year}${month}${String(
|
const waybillNumber = `IRS${year}${month}${String(Math.floor(Math.random() * 10000)).padStart(
|
||||||
Math.floor(Math.random() * 10000)
|
4,
|
||||||
).padStart(4, "0")}`;
|
'0',
|
||||||
|
)}`
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
waybillNumber,
|
waybillNumber,
|
||||||
waybillDate: now,
|
waybillDate: now,
|
||||||
deliveryDate: now,
|
deliveryDate: now,
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
}, [waybill]);
|
}, [waybill])
|
||||||
|
|
||||||
const calculateItemTotal = (item: Partial<FiWaybillItem>) => {
|
const calculateItemTotal = (item: Partial<FiWaybillItem>) => {
|
||||||
const subtotal = (item.quantity || 0) * (item.unitPrice || 0);
|
const subtotal = (item.quantity || 0) * (item.unitPrice || 0)
|
||||||
const discountAmount = subtotal * ((item.discountRate || 0) / 100);
|
const discountAmount = subtotal * ((item.discountRate || 0) / 100)
|
||||||
const taxableAmount = subtotal - discountAmount;
|
const taxableAmount = subtotal - discountAmount
|
||||||
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100);
|
const taxAmount = taxableAmount * ((item.taxRate || 0) / 100)
|
||||||
return taxableAmount + taxAmount;
|
return taxableAmount + taxAmount
|
||||||
};
|
}
|
||||||
|
|
||||||
const calculateWaybillTotals = (items: FiWaybillItem[]) => {
|
const calculateWaybillTotals = (items: FiWaybillItem[]) => {
|
||||||
const subtotal = items.reduce(
|
const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0)
|
||||||
(sum, item) => sum + item.quantity * item.unitPrice,
|
const discountAmount = items.reduce((sum, item) => sum + item.discountAmount, 0)
|
||||||
0
|
const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0)
|
||||||
);
|
const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0)
|
||||||
const discountAmount = items.reduce(
|
|
||||||
(sum, item) => sum + item.discountAmount,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const taxAmount = items.reduce((sum, item) => sum + item.taxAmount, 0);
|
|
||||||
const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subtotal,
|
subtotal,
|
||||||
discountAmount,
|
discountAmount,
|
||||||
taxAmount,
|
taxAmount,
|
||||||
totalAmount,
|
totalAmount,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleAddItem = () => {
|
const handleAddItem = () => {
|
||||||
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
|
if (!newItem.description || !newItem.quantity || !newItem.unitPrice) {
|
||||||
alert("Lütfen ürün bilgilerini doldurun");
|
alert('Lütfen ürün bilgilerini doldurun')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0);
|
const subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0)
|
||||||
const discountAmount = subtotal * ((newItem.discountRate || 0) / 100);
|
const discountAmount = subtotal * ((newItem.discountRate || 0) / 100)
|
||||||
const taxableAmount = subtotal - discountAmount;
|
const taxableAmount = subtotal - discountAmount
|
||||||
const taxAmount = taxableAmount * ((newItem.taxRate || 0) / 100);
|
const taxAmount = taxableAmount * ((newItem.taxRate || 0) / 100)
|
||||||
|
|
||||||
const item: FiWaybillItem = {
|
const item: FiWaybillItem = {
|
||||||
id: Date.now().toString(),
|
id: Date.now().toString(),
|
||||||
waybillId: formData.id || "",
|
waybillId: formData.id || '',
|
||||||
description: newItem.description!,
|
description: newItem.description!,
|
||||||
quantity: newItem.quantity!,
|
quantity: newItem.quantity!,
|
||||||
unitPrice: newItem.unitPrice!,
|
unitPrice: newItem.unitPrice!,
|
||||||
unit: newItem.unit || "Adet",
|
unit: newItem.unit || 'Adet',
|
||||||
taxRate: newItem.taxRate || 18,
|
taxRate: newItem.taxRate || 18,
|
||||||
discountRate: newItem.discountRate || 0,
|
discountRate: newItem.discountRate || 0,
|
||||||
lineTotal: calculateItemTotal(newItem),
|
lineTotal: calculateItemTotal(newItem),
|
||||||
discountAmount,
|
discountAmount,
|
||||||
taxAmount,
|
taxAmount,
|
||||||
netAmount: taxableAmount,
|
netAmount: taxableAmount,
|
||||||
};
|
}
|
||||||
|
|
||||||
const updatedItems = [...(formData.items || []), item];
|
const updatedItems = [...(formData.items || []), item]
|
||||||
const totals = calculateWaybillTotals(updatedItems);
|
const totals = calculateWaybillTotals(updatedItems)
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
items: updatedItems,
|
items: updatedItems,
|
||||||
...totals,
|
...totals,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
setNewItem({
|
setNewItem({
|
||||||
description: "",
|
description: '',
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
unitPrice: 0,
|
unitPrice: 0,
|
||||||
taxRate: 18,
|
taxRate: 18,
|
||||||
discountRate: 0,
|
discountRate: 0,
|
||||||
unit: "Adet",
|
unit: 'Adet',
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleRemoveItem = (itemId: string) => {
|
const handleRemoveItem = (itemId: string) => {
|
||||||
const updatedItems =
|
const updatedItems = formData.items?.filter((item) => item.id !== itemId) || []
|
||||||
formData.items?.filter((item) => item.id !== itemId) || [];
|
const totals = calculateWaybillTotals(updatedItems)
|
||||||
const totals = calculateWaybillTotals(updatedItems);
|
|
||||||
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
items: updatedItems,
|
items: updatedItems,
|
||||||
...totals,
|
...totals,
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (!formData.currentAccountId) {
|
if (!formData.currentAccountId) {
|
||||||
alert("Lütfen cari hesap seçin");
|
alert('Lütfen cari hesap seçin')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (!formData.items?.length) {
|
if (!formData.items?.length) {
|
||||||
alert("Lütfen en az bir ürün ekleyin");
|
alert('Lütfen en az bir ürün ekleyin')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
onSave({
|
onSave({
|
||||||
|
|
@ -180,18 +163,18 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
id: waybill?.id || Date.now().toString(),
|
id: waybill?.id || Date.now().toString(),
|
||||||
creationTime: waybill?.creationTime || new Date(),
|
creationTime: waybill?.creationTime || new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const formatCurrency = (amount: number) => {
|
const formatCurrency = (amount: number) => {
|
||||||
return amount.toLocaleString("tr-TR", {
|
return amount.toLocaleString('tr-TR', {
|
||||||
style: "currency",
|
style: 'currency',
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
|
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
|
||||||
|
|
@ -201,7 +184,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<FaTruck className="w-5 h-5 text-blue-600" />
|
<FaTruck className="w-5 h-5 text-blue-600" />
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{waybill ? "İrsaliye Düzenle" : "Yeni İrsaliye"}
|
{waybill ? 'İrsaliye Düzenle' : 'Yeni İrsaliye'}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -217,24 +200,18 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
{/* Basic Information */}
|
{/* Basic Information */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye No</label>
|
||||||
İrsaliye No
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.waybillNumber}
|
value={formData.waybillNumber}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, waybillNumber: e.target.value })}
|
||||||
setFormData({ ...formData, waybillNumber: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">İrsaliye Türü</label>
|
||||||
İrsaliye Türü
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.waybillType}
|
value={formData.waybillType}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
|
@ -245,23 +222,16 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WaybillTypeEnum.Outgoing}>
|
{Object.values(WaybillTypeEnum).map((type) => (
|
||||||
Çıkış İrsaliyesi
|
<option key={type} value={type}>
|
||||||
</option>
|
{getWaybillTypeText(type)}
|
||||||
<option value={WaybillTypeEnum.Incoming}>
|
</option>
|
||||||
Giriş İrsaliyesi
|
))}
|
||||||
</option>
|
|
||||||
<option value={WaybillTypeEnum.Transfer}>
|
|
||||||
Transfer İrsaliyesi
|
|
||||||
</option>
|
|
||||||
<option value={WaybillTypeEnum.Return}>İade İrsaliyesi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Durum</label>
|
||||||
Durum
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.status}
|
value={formData.status}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
|
@ -272,24 +242,19 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WaybillStatusEnum.Draft}>Taslak</option>
|
{Object.values(WaybillStatusEnum).map((status) => (
|
||||||
<option value={WaybillStatusEnum.Confirmed}>Onaylandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={WaybillStatusEnum.Delivered}>
|
{getWaybillStatusText(status)}
|
||||||
Teslim Edildi
|
</option>
|
||||||
</option>
|
))}
|
||||||
<option value={WaybillStatusEnum.Cancelled}>İptal</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Cari Hesap</label>
|
||||||
Cari Hesap
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currentAccountId}
|
value={formData.currentAccountId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, currentAccountId: e.target.value })}
|
||||||
setFormData({ ...formData, currentAccountId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
|
|
@ -308,7 +273,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.waybillDate?.toISOString().split("T")[0]}
|
value={formData.waybillDate?.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -321,12 +286,10 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Teslim Tarihi</label>
|
||||||
Teslim Tarihi
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.deliveryDate?.toISOString().split("T")[0]}
|
value={formData.deliveryDate?.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -340,16 +303,14 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
|
|
||||||
{/* Delivery Information */}
|
{/* Delivery Information */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">Teslimat Bilgileri</h3>
|
||||||
Teslimat Bilgileri
|
|
||||||
</h3>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
Teslimat Adresi
|
Teslimat Adresi
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.deliveryAddress || ""}
|
value={formData.deliveryAddress || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -362,15 +323,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Alıcı Adı</label>
|
||||||
Alıcı Adı
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.receiverName || ""}
|
value={formData.receiverName || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, receiverName: e.target.value })}
|
||||||
setFormData({ ...formData, receiverName: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -380,7 +337,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.receiverPhone || ""}
|
value={formData.receiverPhone || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -397,10 +354,8 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.carrierCompany || ""}
|
value={formData.carrierCompany || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, carrierCompany: e.target.value })}
|
||||||
setFormData({ ...formData, carrierCompany: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -410,10 +365,8 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.trackingNumber || ""}
|
value={formData.trackingNumber || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, trackingNumber: e.target.value })}
|
||||||
setFormData({ ...formData, trackingNumber: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -422,9 +375,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
|
|
||||||
{/* Waybill Items */}
|
{/* Waybill Items */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">İrsaliye Kalemleri</h3>
|
||||||
İrsaliye Kalemleri
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{/* Add New Item */}
|
{/* Add New Item */}
|
||||||
<div className="bg-gray-50 p-3 rounded-lg mb-3">
|
<div className="bg-gray-50 p-3 rounded-lg mb-3">
|
||||||
|
|
@ -435,21 +386,17 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={newItem.description || ""}
|
value={newItem.description || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
|
||||||
setNewItem({ ...newItem, description: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Ürün/Hizmet açıklaması"
|
placeholder="Ürün/Hizmet açıklaması"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Miktar</label>
|
||||||
Miktar
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={newItem.quantity || ""}
|
value={newItem.quantity || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewItem({
|
setNewItem({
|
||||||
...newItem,
|
...newItem,
|
||||||
|
|
@ -462,15 +409,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Birim</label>
|
||||||
Birim
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={newItem.unit || ""}
|
value={newItem.unit || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setNewItem({ ...newItem, unit: e.target.value })}
|
||||||
setNewItem({ ...newItem, unit: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Adet"
|
placeholder="Adet"
|
||||||
/>
|
/>
|
||||||
|
|
@ -481,7 +424,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={newItem.unitPrice || ""}
|
value={newItem.unitPrice || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewItem({
|
setNewItem({
|
||||||
...newItem,
|
...newItem,
|
||||||
|
|
@ -535,15 +478,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
<tbody className="divide-y divide-gray-200">
|
<tbody className="divide-y divide-gray-200">
|
||||||
{formData.items.map((item) => (
|
{formData.items.map((item) => (
|
||||||
<tr key={item.id} className="text-sm">
|
<tr key={item.id} className="text-sm">
|
||||||
<td className="px-3 py-2 text-gray-900">
|
<td className="px-3 py-2 text-gray-900">{item.description}</td>
|
||||||
{item.description}
|
|
||||||
</td>
|
|
||||||
<td className="px-3 py-2 text-gray-900 text-right">
|
<td className="px-3 py-2 text-gray-900 text-right">
|
||||||
{item.quantity.toLocaleString("tr-TR")}
|
{item.quantity.toLocaleString('tr-TR')}
|
||||||
</td>
|
|
||||||
<td className="px-3 py-2 text-gray-900 text-center">
|
|
||||||
{item.unit}
|
|
||||||
</td>
|
</td>
|
||||||
|
<td className="px-3 py-2 text-gray-900 text-center">{item.unit}</td>
|
||||||
<td className="px-3 py-2 text-gray-900 text-right">
|
<td className="px-3 py-2 text-gray-900 text-right">
|
||||||
{formatCurrency(item.unitPrice)}
|
{formatCurrency(item.unitPrice)}
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -571,14 +510,10 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
<div className="bg-gray-50 p-4 rounded-lg mb-4">
|
<div className="bg-gray-50 p-4 rounded-lg mb-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Notlar</label>
|
||||||
Notlar
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.notes || ""}
|
value={formData.notes || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
|
||||||
setFormData({ ...formData, notes: e.target.value })
|
|
||||||
}
|
|
||||||
rows={4}
|
rows={4}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="İrsaliye ile ilgili notlar..."
|
placeholder="İrsaliye ile ilgili notlar..."
|
||||||
|
|
@ -587,9 +522,7 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-600">Ara Toplam:</span>
|
<span className="text-sm text-gray-600">Ara Toplam:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{formatCurrency(formData.subtotal || 0)}</span>
|
||||||
{formatCurrency(formData.subtotal || 0)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-600">İndirim:</span>
|
<span className="text-sm text-gray-600">İndirim:</span>
|
||||||
|
|
@ -599,15 +532,11 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-600">KDV:</span>
|
<span className="text-sm text-gray-600">KDV:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">{formatCurrency(formData.taxAmount || 0)}</span>
|
||||||
{formatCurrency(formData.taxAmount || 0)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t pt-3">
|
<div className="border-t pt-3">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-base font-semibold text-gray-900">
|
<span className="text-base font-semibold text-gray-900">Genel Toplam:</span>
|
||||||
Genel Toplam:
|
|
||||||
</span>
|
|
||||||
<span className="text-base font-bold text-blue-600">
|
<span className="text-base font-bold text-blue-600">
|
||||||
{formatCurrency(formData.totalAmount || 0)}
|
{formatCurrency(formData.totalAmount || 0)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -631,13 +560,13 @@ const WaybillForm: React.FC<WaybillFormProps> = ({
|
||||||
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2"
|
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{waybill ? "Güncelle" : "Kaydet"}
|
{waybill ? 'Güncelle' : 'Kaydet'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default WaybillForm;
|
export default WaybillForm
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from 'react'
|
||||||
import {
|
import {
|
||||||
FaPlus,
|
FaPlus,
|
||||||
FaSearch,
|
FaSearch,
|
||||||
|
|
@ -9,28 +9,24 @@ import {
|
||||||
FaTruck,
|
FaTruck,
|
||||||
FaCheck,
|
FaCheck,
|
||||||
FaEye,
|
FaEye,
|
||||||
} from "react-icons/fa";
|
} from 'react-icons/fa'
|
||||||
import {
|
import { FiWaybill, WaybillTypeEnum, WaybillStatusEnum } from '../../../types/fi'
|
||||||
FiWaybill,
|
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||||
WaybillTypeEnum,
|
import Widget from '../../../components/common/Widget'
|
||||||
WaybillStatusEnum,
|
|
||||||
} from "../../../types/fi";
|
|
||||||
import DataTable, { Column } from "../../../components/common/DataTable";
|
|
||||||
import Widget from "../../../components/common/Widget";
|
|
||||||
import {
|
import {
|
||||||
getWaybillStatusColor,
|
getWaybillStatusColor,
|
||||||
getWaybillStatusText,
|
getWaybillStatusText,
|
||||||
getWaybillTypeColor,
|
getWaybillTypeColor,
|
||||||
getWaybillTypeText,
|
getWaybillTypeText,
|
||||||
} from "../../../utils/erp";
|
} from '../../../utils/erp'
|
||||||
|
|
||||||
interface WaybillManagementProps {
|
interface WaybillManagementProps {
|
||||||
waybills: FiWaybill[];
|
waybills: FiWaybill[]
|
||||||
onAdd: () => void;
|
onAdd: () => void
|
||||||
onEdit: (waybill: FiWaybill) => void;
|
onEdit: (waybill: FiWaybill) => void
|
||||||
onViewDetails: (waybill: FiWaybill) => void;
|
onViewDetails: (waybill: FiWaybill) => void
|
||||||
onCreateInvoice: (waybill: FiWaybill) => void;
|
onCreateInvoice: (waybill: FiWaybill) => void
|
||||||
onMarkAsDelivered: (waybill: FiWaybill) => void;
|
onMarkAsDelivered: (waybill: FiWaybill) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
|
|
@ -41,109 +37,87 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
onCreateInvoice,
|
onCreateInvoice,
|
||||||
onMarkAsDelivered,
|
onMarkAsDelivered,
|
||||||
}) => {
|
}) => {
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [selectedType, setSelectedType] = useState<WaybillTypeEnum | "all">(
|
const [selectedType, setSelectedType] = useState<WaybillTypeEnum | 'all'>('all')
|
||||||
"all"
|
const [selectedStatus, setSelectedStatus] = useState<WaybillStatusEnum | 'all'>('all')
|
||||||
);
|
const [showInvoicedOnly, setShowInvoicedOnly] = useState<'all' | 'invoiced' | 'not_invoiced'>(
|
||||||
const [selectedStatus, setSelectedStatus] = useState<
|
'not_invoiced',
|
||||||
WaybillStatusEnum | "all"
|
)
|
||||||
>("all");
|
const [sortBy, setSortBy] = useState<'date' | 'amount' | 'deliveryDate'>('date')
|
||||||
const [showInvoicedOnly, setShowInvoicedOnly] = useState<
|
|
||||||
"all" | "invoiced" | "not_invoiced"
|
|
||||||
>("not_invoiced");
|
|
||||||
const [sortBy, setSortBy] = useState<"date" | "amount" | "deliveryDate">(
|
|
||||||
"date"
|
|
||||||
);
|
|
||||||
|
|
||||||
const filteredWaybills = waybills
|
const filteredWaybills = waybills
|
||||||
.filter((waybill) => {
|
.filter((waybill) => {
|
||||||
if (
|
if (
|
||||||
searchTerm &&
|
searchTerm &&
|
||||||
!waybill.waybillNumber
|
!waybill.waybillNumber.toLowerCase().includes(searchTerm.toLowerCase()) &&
|
||||||
.toLowerCase()
|
!waybill.currentAccount?.accountCode?.toLowerCase().includes(searchTerm.toLowerCase()) &&
|
||||||
.includes(searchTerm.toLowerCase()) &&
|
!waybill.trackingNumber?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
!waybill.currentAccount?.accountCode
|
|
||||||
?.toLowerCase()
|
|
||||||
.includes(searchTerm.toLowerCase()) &&
|
|
||||||
!waybill.trackingNumber
|
|
||||||
?.toLowerCase()
|
|
||||||
.includes(searchTerm.toLowerCase())
|
|
||||||
) {
|
) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (selectedType !== "all" && waybill.waybillType !== selectedType) {
|
if (selectedType !== 'all' && waybill.waybillType !== selectedType) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (selectedStatus !== "all" && waybill.status !== selectedStatus) {
|
if (selectedStatus !== 'all' && waybill.status !== selectedStatus) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (showInvoicedOnly === "invoiced" && !waybill.isInvoiced) {
|
if (showInvoicedOnly === 'invoiced' && !waybill.isInvoiced) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (showInvoicedOnly === "not_invoiced" && waybill.isInvoiced) {
|
if (showInvoicedOnly === 'not_invoiced' && waybill.isInvoiced) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
switch (sortBy) {
|
switch (sortBy) {
|
||||||
case "date":
|
case 'date':
|
||||||
return (
|
return new Date(b.waybillDate).getTime() - new Date(a.waybillDate).getTime()
|
||||||
new Date(b.waybillDate).getTime() -
|
case 'amount':
|
||||||
new Date(a.waybillDate).getTime()
|
return b.totalAmount - a.totalAmount
|
||||||
);
|
case 'deliveryDate':
|
||||||
case "amount":
|
if (!a.deliveryDate && !b.deliveryDate) return 0
|
||||||
return b.totalAmount - a.totalAmount;
|
if (!a.deliveryDate) return 1
|
||||||
case "deliveryDate":
|
if (!b.deliveryDate) return -1
|
||||||
if (!a.deliveryDate && !b.deliveryDate) return 0;
|
return new Date(a.deliveryDate).getTime() - new Date(b.deliveryDate).getTime()
|
||||||
if (!a.deliveryDate) return 1;
|
|
||||||
if (!b.deliveryDate) return -1;
|
|
||||||
return (
|
|
||||||
new Date(a.deliveryDate).getTime() -
|
|
||||||
new Date(b.deliveryDate).getTime()
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const formatCurrency = (amount: number) => {
|
const formatCurrency = (amount: number) => {
|
||||||
return amount.toLocaleString("tr-TR", {
|
return amount.toLocaleString('tr-TR', {
|
||||||
style: "currency",
|
style: 'currency',
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
const formatDate = (date: Date) => {
|
const formatDate = (date: Date) => {
|
||||||
return new Date(date).toLocaleDateString("tr-TR");
|
return new Date(date).toLocaleDateString('tr-TR')
|
||||||
};
|
}
|
||||||
|
|
||||||
const columns: Column<FiWaybill>[] = [
|
const columns: Column<FiWaybill>[] = [
|
||||||
{
|
{
|
||||||
key: "waybillNumber",
|
key: 'waybillNumber',
|
||||||
header: "İrsaliye No",
|
header: 'İrsaliye No',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">{waybill.waybillNumber}</div>
|
||||||
{waybill.waybillNumber}
|
|
||||||
</div>
|
|
||||||
{waybill.trackingNumber && (
|
{waybill.trackingNumber && (
|
||||||
<div className="text-sm text-gray-500">
|
<div className="text-sm text-gray-500">Takip: {waybill.trackingNumber}</div>
|
||||||
Takip: {waybill.trackingNumber}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "type",
|
key: 'type',
|
||||||
header: "Tür",
|
header: 'Tür',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
|
||||||
waybill.waybillType
|
waybill.waybillType,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getWaybillTypeText(waybill.waybillType)}
|
{getWaybillTypeText(waybill.waybillType)}
|
||||||
|
|
@ -151,22 +125,20 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "currentAccount",
|
key: 'currentAccount',
|
||||||
header: "Cari Hesap",
|
header: 'Cari Hesap',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">
|
||||||
{waybill.currentAccount?.accountCode || "Bilinmeyen"}
|
{waybill.currentAccount?.accountCode || 'Bilinmeyen'}
|
||||||
</div>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
{waybill.currentAccount?.accountCode}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-sm text-gray-500">{waybill.currentAccount?.accountCode}</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "dates",
|
key: 'dates',
|
||||||
header: "Tarihler",
|
header: 'Tarihler',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
|
|
@ -183,27 +155,23 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "amounts",
|
key: 'amounts',
|
||||||
header: "Tutarlar",
|
header: 'Tutarlar',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">{formatCurrency(waybill.totalAmount)}</div>
|
||||||
{formatCurrency(waybill.totalAmount)}
|
<div className="text-sm text-gray-500">{waybill.items.length} kalem</div>
|
||||||
</div>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
{waybill.items.length} kalem
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "status",
|
key: 'status',
|
||||||
header: "Durum",
|
header: 'Durum',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
|
||||||
waybill.status
|
waybill.status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getWaybillStatusText(waybill.status)}
|
{getWaybillStatusText(waybill.status)}
|
||||||
|
|
@ -211,25 +179,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
<br />
|
<br />
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${
|
className={`px-2 py-1 text-xs font-medium rounded-full ${
|
||||||
waybill.isInvoiced
|
waybill.isInvoiced ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
|
||||||
? "bg-green-100 text-green-800"
|
|
||||||
: "bg-yellow-100 text-yellow-800"
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{waybill.isInvoiced ? "Faturalandı" : "Faturalanmadı"}
|
{waybill.isInvoiced ? 'Faturalandı' : 'Faturalanmadı'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "carrier",
|
key: 'carrier',
|
||||||
header: "Kargo",
|
header: 'Kargo',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
{waybill.carrierCompany && (
|
{waybill.carrierCompany && (
|
||||||
<div className="font-medium text-gray-900">
|
<div className="font-medium text-gray-900">{waybill.carrierCompany}</div>
|
||||||
{waybill.carrierCompany}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{waybill.receiverName && (
|
{waybill.receiverName && (
|
||||||
<div className="text-gray-500">Alıcı: {waybill.receiverName}</div>
|
<div className="text-gray-500">Alıcı: {waybill.receiverName}</div>
|
||||||
|
|
@ -238,8 +202,8 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "actions",
|
key: 'actions',
|
||||||
header: "İşlemler",
|
header: 'İşlemler',
|
||||||
render: (waybill: FiWaybill) => (
|
render: (waybill: FiWaybill) => (
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
<button
|
<button
|
||||||
|
|
@ -256,16 +220,15 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
>
|
>
|
||||||
<FaEdit className="w-4 h-4" />
|
<FaEdit className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
{!waybill.isInvoiced &&
|
{!waybill.isInvoiced && waybill.status === WaybillStatusEnum.Delivered && (
|
||||||
waybill.status === WaybillStatusEnum.Delivered && (
|
<button
|
||||||
<button
|
onClick={() => onCreateInvoice(waybill)}
|
||||||
onClick={() => onCreateInvoice(waybill)}
|
className="p-1 text-purple-600 hover:bg-purple-50 rounded"
|
||||||
className="p-1 text-purple-600 hover:bg-purple-50 rounded"
|
title="Fatura Oluştur"
|
||||||
title="Fatura Oluştur"
|
>
|
||||||
>
|
<FaFileAlt className="w-4 h-4" />
|
||||||
<FaFileAlt className="w-4 h-4" />
|
</button>
|
||||||
</button>
|
)}
|
||||||
)}
|
|
||||||
{waybill.status === WaybillStatusEnum.Confirmed && (
|
{waybill.status === WaybillStatusEnum.Confirmed && (
|
||||||
<button
|
<button
|
||||||
onClick={() => onMarkAsDelivered(waybill)}
|
onClick={() => onMarkAsDelivered(waybill)}
|
||||||
|
|
@ -278,18 +241,13 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
||||||
// Calculate statistics
|
// Calculate statistics
|
||||||
const totalWaybills = waybills.length;
|
const totalWaybills = waybills.length
|
||||||
const notInvoicedWaybills = waybills.filter((w) => !w.isInvoiced);
|
const notInvoicedWaybills = waybills.filter((w) => !w.isInvoiced)
|
||||||
const deliveredWaybills = waybills.filter(
|
const deliveredWaybills = waybills.filter((w) => w.status === WaybillStatusEnum.Delivered)
|
||||||
(w) => w.status === WaybillStatusEnum.Delivered
|
const totalNotInvoicedAmount = notInvoicedWaybills.reduce((sum, w) => sum + w.totalAmount, 0)
|
||||||
);
|
|
||||||
const totalNotInvoicedAmount = notInvoicedWaybills.reduce(
|
|
||||||
(sum, w) => sum + w.totalAmount,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
// Waybill type distribution
|
// Waybill type distribution
|
||||||
const typeDistribution = Object.values(WaybillTypeEnum).map((type) => ({
|
const typeDistribution = Object.values(WaybillTypeEnum).map((type) => ({
|
||||||
|
|
@ -298,16 +256,14 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
amount: waybills
|
amount: waybills
|
||||||
.filter((w) => w.waybillType === type)
|
.filter((w) => w.waybillType === type)
|
||||||
.reduce((sum, w) => sum + w.totalAmount, 0),
|
.reduce((sum, w) => sum + w.totalAmount, 0),
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// Status distribution
|
// Status distribution
|
||||||
const statusDistribution = Object.values(WaybillStatusEnum).map((status) => ({
|
const statusDistribution = Object.values(WaybillStatusEnum).map((status) => ({
|
||||||
status,
|
status,
|
||||||
count: waybills.filter((w) => w.status === status).length,
|
count: waybills.filter((w) => w.status === status).length,
|
||||||
amount: waybills
|
amount: waybills.filter((w) => w.status === status).reduce((sum, w) => sum + w.totalAmount, 0),
|
||||||
.filter((w) => w.status === status)
|
}))
|
||||||
.reduce((sum, w) => sum + w.totalAmount, 0),
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|
@ -315,9 +271,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900">İrsaliye Yönetimi</h2>
|
<h2 className="text-2xl font-bold text-gray-900">İrsaliye Yönetimi</h2>
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600">Giriş ve çıkış irsaliyeleri yönetimi</p>
|
||||||
Giriş ve çıkış irsaliyeleri yönetimi
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 text-sm">
|
<div className="flex gap-2 text-sm">
|
||||||
<button
|
<button
|
||||||
|
|
@ -332,12 +286,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
|
|
||||||
{/* Stats Cards */}
|
{/* Stats Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||||
<Widget
|
<Widget title="Toplam İrsaliye" value={totalWaybills} color="blue" icon="FaFileAlt" />
|
||||||
title="Toplam İrsaliye"
|
|
||||||
value={totalWaybills}
|
|
||||||
color="blue"
|
|
||||||
icon="FaFileAlt"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Widget
|
<Widget
|
||||||
title="Faturalanmamış"
|
title="Faturalanmamış"
|
||||||
|
|
@ -364,25 +313,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
{/* Distribution Charts */}
|
{/* Distribution Charts */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">İrsaliye Türü Dağılımı</h3>
|
||||||
İrsaliye Türü Dağılımı
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{typeDistribution.map(({ type, count, amount }) => (
|
{typeDistribution.map(({ type, count, amount }) => (
|
||||||
<div key={type} className="flex items-center justify-between">
|
<div key={type} className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillTypeColor(
|
||||||
type
|
type,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getWaybillTypeText(type)}
|
{getWaybillTypeText(type)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span className="text-sm text-gray-600">
|
<span className="text-sm text-gray-600">{count} irsaliye</span>
|
||||||
{count} irsaliye
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium text-gray-900">
|
<span className="text-sm font-medium text-gray-900">
|
||||||
{formatCurrency(amount)}
|
{formatCurrency(amount)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -393,25 +338,21 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow-sm border p-4">
|
<div className="bg-white rounded-lg shadow-sm border p-4">
|
||||||
<h3 className="text-base font-semibold text-gray-900 mb-3">
|
<h3 className="text-base font-semibold text-gray-900 mb-3">Durum Dağılımı</h3>
|
||||||
Durum Dağılımı
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{statusDistribution.map(({ status, count, amount }) => (
|
{statusDistribution.map(({ status, count, amount }) => (
|
||||||
<div key={status} className="flex items-center justify-between">
|
<div key={status} className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
|
className={`px-2 py-1 text-xs font-medium rounded-full ${getWaybillStatusColor(
|
||||||
status
|
status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getWaybillStatusText(status)}
|
{getWaybillStatusText(status)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span className="text-sm text-gray-600">
|
<span className="text-sm text-gray-600">{count} irsaliye</span>
|
||||||
{count} irsaliye
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium text-gray-900">
|
<span className="text-sm font-medium text-gray-900">
|
||||||
{formatCurrency(amount)}
|
{formatCurrency(amount)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -427,13 +368,11 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
<div className="bg-orange-50 border border-orange-200 rounded-lg p-3">
|
<div className="bg-orange-50 border border-orange-200 rounded-lg p-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<FaExclamationTriangle className="w-5 h-5 text-orange-600" />
|
<FaExclamationTriangle className="w-5 h-5 text-orange-600" />
|
||||||
<h3 className="text-base font-semibold text-orange-900">
|
<h3 className="text-base font-semibold text-orange-900">Faturalanmamış İrsaliyeler</h3>
|
||||||
Faturalanmamış İrsaliyeler
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-orange-700 mt-1">
|
<p className="text-sm text-orange-700 mt-1">
|
||||||
{notInvoicedWaybills.length} adet irsaliye henüz faturalanmamış.
|
{notInvoicedWaybills.length} adet irsaliye henüz faturalanmamış. Toplam tutar:{' '}
|
||||||
Toplam tutar: {formatCurrency(totalNotInvoicedAmount)}
|
{formatCurrency(totalNotInvoicedAmount)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -453,9 +392,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={selectedType}
|
value={selectedType}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSelectedType(e.target.value as WaybillTypeEnum | 'all')}
|
||||||
setSelectedType(e.target.value as WaybillTypeEnum | "all")
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Türler</option>
|
<option value="all">Tüm Türler</option>
|
||||||
|
|
@ -468,9 +405,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={selectedStatus}
|
value={selectedStatus}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSelectedStatus(e.target.value as WaybillStatusEnum | 'all')}
|
||||||
setSelectedStatus(e.target.value as WaybillStatusEnum | "all")
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
|
|
@ -484,9 +419,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
<select
|
<select
|
||||||
value={showInvoicedOnly}
|
value={showInvoicedOnly}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setShowInvoicedOnly(
|
setShowInvoicedOnly(e.target.value as 'all' | 'invoiced' | 'not_invoiced')
|
||||||
e.target.value as "all" | "invoiced" | "not_invoiced"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
|
|
@ -497,9 +430,7 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={sortBy}
|
value={sortBy}
|
||||||
onChange={(e) =>
|
onChange={(e) => setSortBy(e.target.value as 'date' | 'amount' | 'deliveryDate')}
|
||||||
setSortBy(e.target.value as "date" | "amount" | "deliveryDate")
|
|
||||||
}
|
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="date">Tarihe Göre</option>
|
<option value="date">Tarihe Göre</option>
|
||||||
|
|
@ -516,16 +447,14 @@ const WaybillManagement: React.FC<WaybillManagementProps> = ({
|
||||||
{filteredWaybills.length === 0 && (
|
{filteredWaybills.length === 0 && (
|
||||||
<div className="text-center py-10">
|
<div className="text-center py-10">
|
||||||
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
|
<FaFileAlt className="w-12 h-12 text-gray-400 mx-auto mb-4" />
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-2">
|
<h3 className="text-base font-medium text-gray-900 mb-2">İrsaliye bulunamadı</h3>
|
||||||
İrsaliye bulunamadı
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
Yeni bir irsaliye ekleyin veya arama kriterlerinizi değiştirin.
|
Yeni bir irsaliye ekleyin veya arama kriterlerinizi değiştirin.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default WaybillManagement;
|
export default WaybillManagement
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ import Widget from '../../../components/common/Widget'
|
||||||
import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
|
import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
|
||||||
import {
|
import {
|
||||||
getBusinessPartyStatusColor,
|
getBusinessPartyStatusColor,
|
||||||
getBusinessPartyStatusName,
|
getBusinessPartyStatusText,
|
||||||
getCustomerSegmentName,
|
getCustomerSegmentText,
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
|
||||||
|
|
@ -177,10 +177,11 @@ const CustomerCards: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option>
|
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||||
<option value={BusinessPartyStatusEnum.Active}>Aktif</option>
|
<option key={status} value={status}>
|
||||||
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option>
|
{getBusinessPartyStatusText(status)}
|
||||||
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -192,10 +193,11 @@ const CustomerCards: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option>
|
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||||
<option value={CustomerSegmentEnum.SMB}>KOBİ</option>
|
<option key={segment} value={segment}>
|
||||||
<option value={CustomerSegmentEnum.Startup}>Girişim</option>
|
{getCustomerSegmentText(segment)}
|
||||||
<option value={CustomerSegmentEnum.Government}>Kamu</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -289,7 +291,7 @@ const CustomerCards: React.FC = () => {
|
||||||
{customer.code}
|
{customer.code}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-gray-600">
|
<p className="text-sm text-gray-600">
|
||||||
{getCustomerSegmentName(customer.customerSegment!)}
|
{getCustomerSegmentText(customer.customerSegment!)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -299,7 +301,7 @@ const CustomerCards: React.FC = () => {
|
||||||
getBusinessPartyStatusColor(customer.status!),
|
getBusinessPartyStatusColor(customer.status!),
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{getBusinessPartyStatusName(customer.status!)}
|
{getBusinessPartyStatusText(customer.status!)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,13 @@ import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBu
|
||||||
import { BusinessParty, BusinessPartyStatusEnum, PaymentTerms } from '../../../types/common'
|
import { BusinessParty, BusinessPartyStatusEnum, PaymentTerms } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import {
|
||||||
|
getBusinessPartyStatusText,
|
||||||
|
getCustomerSegmentText,
|
||||||
|
getCustomerTypeText,
|
||||||
|
getPaymentTermsText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
const CustomerEdit: React.FC = () => {
|
const CustomerEdit: React.FC = () => {
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
|
|
@ -316,10 +323,11 @@ const CustomerEdit: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('customerType', e.target.value)}
|
onChange={(e) => handleInputChange('customerType', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value={CustomerTypeEnum.Company}>Şirket</option>
|
{Object.values(CustomerTypeEnum).map((type) => (
|
||||||
<option value={CustomerTypeEnum.Individual}>Bireysel</option>
|
<option key={type} value={type}>
|
||||||
<option value={CustomerTypeEnum.Government}>Kamu</option>
|
{getCustomerTypeText(type)}
|
||||||
<option value={CustomerTypeEnum.NonProfit}>Kar Amacı Gütmeyen</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -354,10 +362,11 @@ const CustomerEdit: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('status', e.target.value)}
|
onChange={(e) => handleInputChange('status', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option>
|
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||||
<option value={BusinessPartyStatusEnum.Active}>Aktif</option>
|
<option key={status} value={status}>
|
||||||
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option>
|
{getBusinessPartyStatusText(status)}
|
||||||
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -370,10 +379,11 @@ const CustomerEdit: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('customerSegment', e.target.value)}
|
onChange={(e) => handleInputChange('customerSegment', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option>
|
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||||
<option value={CustomerSegmentEnum.SMB}>KOBİ</option>
|
<option key={segment} value={segment}>
|
||||||
<option value={CustomerSegmentEnum.Startup}>Girişim</option>
|
{getCustomerSegmentText(segment)}
|
||||||
<option value={CustomerSegmentEnum.Government}>Kamu</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -644,10 +654,11 @@ const CustomerEdit: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="TRY">Türk Lirası (TRY)</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">Amerikan Doları (USD)</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">Euro (EUR)</option>
|
{currency.value} - {currency.label}
|
||||||
<option value="GBP">İngiliz Sterlini (GBP)</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -660,11 +671,11 @@ const CustomerEdit: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
|
onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value={PaymentTerms.Prepaid}>Peşin</option>
|
{Object.values(PaymentTerms).map((term) => (
|
||||||
<option value={PaymentTerms.COD}>Kapıda Ödeme</option>
|
<option key={term} value={term}>
|
||||||
<option value={PaymentTerms.Net30}>30 Gün Vade</option>
|
{getPaymentTermsText(term)}
|
||||||
<option value={PaymentTerms.Net60}>60 Gün Vade</option>
|
</option>
|
||||||
<option value={PaymentTerms.Net90}>90 Gün Vade</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,23 @@ import {
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import LoadingSpinner from '../../../components/common/LoadingSpinner'
|
import LoadingSpinner from '../../../components/common/LoadingSpinner'
|
||||||
import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBusinessParties'
|
import { mockBusinessParties, mockBusinessPartyNew } from '../../../mocks/mockBusinessParties'
|
||||||
import { BusinessParty } from '../../../types/common'
|
import {
|
||||||
|
BusinessParty,
|
||||||
|
BusinessPartyIndustryEnum,
|
||||||
|
BusinessPartyStatusEnum,
|
||||||
|
PaymentTerms,
|
||||||
|
} from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
import {
|
||||||
|
getBusinessPartyIndustryText,
|
||||||
|
getBusinessPartyStatusText,
|
||||||
|
getCustomerSegmentText,
|
||||||
|
getCustomerTypeText,
|
||||||
|
getPaymentTermsText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
import { CustomerSegmentEnum, CustomerTypeEnum } from '@/types/crm'
|
||||||
|
|
||||||
interface ValidationErrors {
|
interface ValidationErrors {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
|
|
@ -181,8 +195,11 @@ const CustomerForm: React.FC = () => {
|
||||||
}
|
}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="COMPANY">Şirket</option>
|
{Object.values(CustomerTypeEnum).map((type) => (
|
||||||
<option value="INDIVIDUAL">Bireysel</option>
|
<option key={type} value={type}>
|
||||||
|
{getCustomerTypeText(type)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -216,14 +233,11 @@ const CustomerForm: React.FC = () => {
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Sektör seçin</option>
|
<option value="">Sektör seçin</option>
|
||||||
<option value="TECHNOLOGY">Teknoloji</option>
|
{Object.values(BusinessPartyIndustryEnum).map((industry) => (
|
||||||
<option value="MANUFACTURING">İmalat</option>
|
<option key={industry} value={industry}>
|
||||||
<option value="CONSTRUCTION">İnşaat</option>
|
{getBusinessPartyIndustryText(industry)}
|
||||||
<option value="AUTOMOTIVE">Otomotiv</option>
|
</option>
|
||||||
<option value="RETAIL">Perakende</option>
|
))}
|
||||||
<option value="FINANCE">Finans</option>
|
|
||||||
<option value="HEALTHCARE">Sağlık</option>
|
|
||||||
<option value="OTHER">Diğer</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -369,11 +383,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
|
onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="CASH">Peşin</option>
|
{Object.values(PaymentTerms).map((term) => (
|
||||||
<option value="NET_15">15 Gün Vadeli</option>
|
<option key={term} value={term}>
|
||||||
<option value="NET_30">30 Gün Vadeli</option>
|
{getPaymentTermsText(term)}
|
||||||
<option value="NET_60">60 Gün Vadeli</option>
|
</option>
|
||||||
<option value="NET_90">90 Gün Vadeli</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -386,9 +400,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">Türk Lirası (TRY)</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">Amerikan Doları (USD)</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">Euro (EUR)</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -415,10 +431,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('status', e.target.value)}
|
onChange={(e) => handleInputChange('status', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="ACTIVE">Aktif</option>
|
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||||
<option value="INACTIVE">Pasif</option>
|
<option key={status} value={status}>
|
||||||
<option value="PROSPECT">Potansiyel</option>
|
{getBusinessPartyStatusText(status)}
|
||||||
<option value="BLOCKED">Blokeli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -431,10 +448,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('customerSegment', e.target.value)}
|
onChange={(e) => handleInputChange('customerSegment', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="STANDARD">Standart</option>
|
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||||
<option value="PREMIUM">Premium</option>
|
<option key={segment} value={segment}>
|
||||||
<option value="ENTERPRISE">Kurumsal</option>
|
{getCustomerSegmentText(segment)}
|
||||||
<option value="VIP">VIP</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -442,16 +460,13 @@ const CustomerForm: React.FC = () => {
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||||
Sorumlu Satış Temsilcisi
|
Sorumlu Satış Temsilcisi
|
||||||
</label>
|
</label>
|
||||||
<select
|
<input
|
||||||
|
type="text"
|
||||||
value={formData.assignedSalesRep}
|
value={formData.assignedSalesRep}
|
||||||
onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)}
|
onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
placeholder="Satış temsilcisi adı"
|
||||||
<option value="">Temsilci seçin</option>
|
/>
|
||||||
<option value="sales_rep_1">Mehmet Özkan</option>
|
|
||||||
<option value="sales_rep_2">Ayşe Demir</option>
|
|
||||||
<option value="sales_rep_3">Ali Yılmaz</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,24 @@ import {
|
||||||
FaEnvelope,
|
FaEnvelope,
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import LoadingSpinner from '../../../components/common/LoadingSpinner'
|
import LoadingSpinner from '../../../components/common/LoadingSpinner'
|
||||||
import { BusinessParty } from '../../../types/common'
|
import {
|
||||||
|
BusinessParty,
|
||||||
|
BusinessPartyIndustryEnum,
|
||||||
|
BusinessPartyStatusEnum,
|
||||||
|
PaymentTerms,
|
||||||
|
} from '../../../types/common'
|
||||||
import { mockBusinessPartyNew } from '../../../mocks/mockBusinessParties'
|
import { mockBusinessPartyNew } from '../../../mocks/mockBusinessParties'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
import { CustomerSegmentEnum, CustomerTypeEnum } from '@/types/crm'
|
||||||
|
import {
|
||||||
|
getBusinessPartyIndustryText,
|
||||||
|
getBusinessPartyStatusText,
|
||||||
|
getCustomerSegmentText,
|
||||||
|
getCustomerTypeText,
|
||||||
|
getPaymentTermsText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
|
||||||
interface ValidationErrors {
|
interface ValidationErrors {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
|
|
@ -174,13 +188,14 @@ const CustomerForm: React.FC = () => {
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={formData.customerType}
|
value={formData.customerType}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('customerType', e.target.value)}
|
||||||
handleInputChange('customerType', e.target.value as 'INDIVIDUAL' | 'COMPANY')
|
|
||||||
}
|
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="COMPANY">Şirket</option>
|
{Object.values(CustomerTypeEnum).map((type) => (
|
||||||
<option value="INDIVIDUAL">Bireysel</option>
|
<option key={type} value={type}>
|
||||||
|
{getCustomerTypeText(type)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -214,14 +229,11 @@ const CustomerForm: React.FC = () => {
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Sektör seçin</option>
|
<option value="">Sektör seçin</option>
|
||||||
<option value="TECHNOLOGY">Teknoloji</option>
|
{Object.values(BusinessPartyIndustryEnum).map((industry) => (
|
||||||
<option value="MANUFACTURING">İmalat</option>
|
<option key={industry} value={industry}>
|
||||||
<option value="CONSTRUCTION">İnşaat</option>
|
{getBusinessPartyIndustryText(industry)}
|
||||||
<option value="AUTOMOTIVE">Otomotiv</option>
|
</option>
|
||||||
<option value="RETAIL">Perakende</option>
|
))}
|
||||||
<option value="FINANCE">Finans</option>
|
|
||||||
<option value="HEALTHCARE">Sağlık</option>
|
|
||||||
<option value="OTHER">Diğer</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -367,11 +379,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
|
onChange={(e) => handleInputChange('paymentTerms', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="CASH">Peşin</option>
|
{Object.values(PaymentTerms).map((term) => (
|
||||||
<option value="NET_15">15 Gün Vadeli</option>
|
<option key={term} value={term}>
|
||||||
<option value="NET_30">30 Gün Vadeli</option>
|
{getPaymentTermsText(term)}
|
||||||
<option value="NET_60">60 Gün Vadeli</option>
|
</option>
|
||||||
<option value="NET_90">90 Gün Vadeli</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -384,9 +396,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">Türk Lirası (TRY)</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">Amerikan Doları (USD)</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">Euro (EUR)</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -413,10 +427,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('status', e.target.value)}
|
onChange={(e) => handleInputChange('status', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="ACTIVE">Aktif</option>
|
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||||
<option value="INACTIVE">Pasif</option>
|
<option key={status} value={status}>
|
||||||
<option value="PROSPECT">Potansiyel</option>
|
{getBusinessPartyStatusText(status)}
|
||||||
<option value="BLOCKED">Blokeli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -429,10 +444,11 @@ const CustomerForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('customerSegment', e.target.value)}
|
onChange={(e) => handleInputChange('customerSegment', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="STANDARD">Standart</option>
|
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||||
<option value="PREMIUM">Premium</option>
|
<option key={segment} value={segment}>
|
||||||
<option value="ENTERPRISE">Kurumsal</option>
|
{getCustomerSegmentText(segment)}
|
||||||
<option value="VIP">VIP</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -440,16 +456,13 @@ const CustomerForm: React.FC = () => {
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||||
Sorumlu Satış Temsilcisi
|
Sorumlu Satış Temsilcisi
|
||||||
</label>
|
</label>
|
||||||
<select
|
<input
|
||||||
|
type="text"
|
||||||
value={formData.assignedSalesRep}
|
value={formData.assignedSalesRep}
|
||||||
onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)}
|
onChange={(e) => handleInputChange('assignedSalesRep', e.target.value)}
|
||||||
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
placeholder="Satış temsilcisi adı"
|
||||||
<option value="">Temsilci seçin</option>
|
/>
|
||||||
<option value="sales_rep_1">Mehmet Özkan</option>
|
|
||||||
<option value="sales_rep_2">Ayşe Demir</option>
|
|
||||||
<option value="sales_rep_3">Ali Yılmaz</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@ import { BusinessPartyStatusEnum, PartyType } from '../../../types/common'
|
||||||
import Widget from '../../../components/common/Widget'
|
import Widget from '../../../components/common/Widget'
|
||||||
import {
|
import {
|
||||||
getBusinessPartyStatusColor,
|
getBusinessPartyStatusColor,
|
||||||
getBusinessPartyStatusName,
|
getBusinessPartyStatusText,
|
||||||
getCustomerSegmentColor,
|
getCustomerSegmentColor,
|
||||||
getCustomerSegmentName,
|
getCustomerSegmentText,
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
|
||||||
|
|
@ -146,10 +146,11 @@ const CustomerList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={BusinessPartyStatusEnum.Prospect}>Potansiyel</option>
|
{Object.values(BusinessPartyStatusEnum).map((status) => (
|
||||||
<option value={BusinessPartyStatusEnum.Active}>Aktif</option>
|
<option key={status} value={status}>
|
||||||
<option value={BusinessPartyStatusEnum.Inactive}>Pasif</option>
|
{getBusinessPartyStatusText(status)}
|
||||||
<option value={BusinessPartyStatusEnum.Blocked}>Blokeli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -161,10 +162,11 @@ const CustomerList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={CustomerSegmentEnum.Enterprise}>Kurumsal</option>
|
{Object.values(CustomerSegmentEnum).map((segment) => (
|
||||||
<option value={CustomerSegmentEnum.SMB}>KOBİ</option>
|
<option key={segment} value={segment}>
|
||||||
<option value={CustomerSegmentEnum.Startup}>Girişim</option>
|
{getCustomerSegmentText(segment)}
|
||||||
<option value={CustomerSegmentEnum.Government}>Kamu</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -310,7 +312,7 @@ const CustomerList: React.FC = () => {
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{getCustomerSegmentName(
|
{getCustomerSegmentText(
|
||||||
customer.customerSegment || CustomerSegmentEnum.SMB,
|
customer.customerSegment || CustomerSegmentEnum.SMB,
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -322,7 +324,7 @@ const CustomerList: React.FC = () => {
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{getBusinessPartyStatusName(
|
{getBusinessPartyStatusText(
|
||||||
customer.status ?? BusinessPartyStatusEnum.Prospect,
|
customer.status ?? BusinessPartyStatusEnum.Prospect,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ import dayjs from 'dayjs'
|
||||||
import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
||||||
import {
|
import {
|
||||||
getBusinessPartyStatusColor,
|
getBusinessPartyStatusColor,
|
||||||
getBusinessPartyStatusName,
|
getBusinessPartyStatusText,
|
||||||
getCustomerSegmentName,
|
getCustomerSegmentText,
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { BusinessPartyStatusEnum } from '../../../types/common'
|
import { BusinessPartyStatusEnum } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
|
@ -167,7 +167,7 @@ const CustomerView: React.FC = () => {
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{getBusinessPartyStatusName(
|
{getBusinessPartyStatusText(
|
||||||
customer.status || BusinessPartyStatusEnum.Active,
|
customer.status || BusinessPartyStatusEnum.Active,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -176,7 +176,7 @@ const CustomerView: React.FC = () => {
|
||||||
<span className="text-sm text-gray-600">{customer.code}</span>
|
<span className="text-sm text-gray-600">{customer.code}</span>
|
||||||
<span className="text-sm text-gray-400">•</span>
|
<span className="text-sm text-gray-400">•</span>
|
||||||
<span className="text-sm text-gray-600">
|
<span className="text-sm text-gray-600">
|
||||||
{getCustomerSegmentName(
|
{getCustomerSegmentText(
|
||||||
customer.customerSegment || CustomerSegmentEnum.Startup,
|
customer.customerSegment || CustomerSegmentEnum.Startup,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -311,7 +311,7 @@ const CustomerView: React.FC = () => {
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600">Segment:</span>
|
<span className="text-gray-600">Segment:</span>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{getCustomerSegmentName(
|
{getCustomerSegmentText(
|
||||||
customer.customerSegment || CustomerSegmentEnum.Startup,
|
customer.customerSegment || CustomerSegmentEnum.Startup,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -729,7 +729,7 @@ const CustomerView: React.FC = () => {
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{getBusinessPartyStatusName(
|
{getBusinessPartyStatusText(
|
||||||
customer.status || BusinessPartyStatusEnum.Active,
|
customer.status || BusinessPartyStatusEnum.Active,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -739,7 +739,7 @@ const CustomerView: React.FC = () => {
|
||||||
Müşteri Segmenti
|
Müşteri Segmenti
|
||||||
</label>
|
</label>
|
||||||
<p className="text-gray-900">
|
<p className="text-gray-900">
|
||||||
{getCustomerSegmentName(
|
{getCustomerSegmentText(
|
||||||
customer.customerSegment || CustomerSegmentEnum.Startup,
|
customer.customerSegment || CustomerSegmentEnum.Startup,
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { mockBusinessParties } from '../../../mocks/mockBusinessParties'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { BusinessParty } from '../../../types/common'
|
import { BusinessParty } from '../../../types/common'
|
||||||
import { getOpportunityLeadSourceText, getOpportunityStageText } from '@/utils/erp'
|
import { getOpportunityLeadSourceText, getOpportunityStageText } from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
interface OpportunityFormProps {
|
interface OpportunityFormProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -353,9 +354,11 @@ const OpportunityForm: React.FC<OpportunityFormProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY - Türk Lirası</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD - Amerikan Doları</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR - Euro</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ import { mockSalesOrders } from '../../../mocks/mockSalesOrders'
|
||||||
import { BusinessParty, PaymentTerms } from '../../../types/common'
|
import { BusinessParty, PaymentTerms } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { getPaymentTermsText, getSaleOrderStatusText } from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
const SalesOrderForm: React.FC = () => {
|
const SalesOrderForm: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
@ -328,13 +330,11 @@ const SalesOrderForm: React.FC = () => {
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={SaleOrderStatusEnum.Draft}>Taslak</option>
|
{Object.values(SaleOrderStatusEnum).map((status) => (
|
||||||
<option value={SaleOrderStatusEnum.Confirmed}>Onaylandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={SaleOrderStatusEnum.InProduction}>Üretimde</option>
|
{getSaleOrderStatusText(status)}
|
||||||
<option value={SaleOrderStatusEnum.Ready}>Hazır</option>
|
</option>
|
||||||
<option value={SaleOrderStatusEnum.Shipped}>Kargoda</option>
|
))}
|
||||||
<option value={SaleOrderStatusEnum.Delivered}>Teslim Edildi</option>
|
|
||||||
<option value={SaleOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -684,9 +684,11 @@ const SalesOrderForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY - Türk Lirası</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD - ABD Doları</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR - Euro</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -746,11 +748,11 @@ const SalesOrderForm: React.FC = () => {
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Seçin...</option>
|
<option value="">Seçin...</option>
|
||||||
<option value="NET30">30 Gün Vadeli</option>
|
{Object.values(PaymentTerms).map((term) => (
|
||||||
<option value="NET60">60 Gün Vadeli</option>
|
<option key={term} value={term}>
|
||||||
<option value="NET90">90 Gün Vadeli</option>
|
{getPaymentTermsText(term)}
|
||||||
<option value="COD">Kapıda Ödeme</option>
|
</option>
|
||||||
<option value="PREPAID">Peşin</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { getTeamRoleText } from '@/utils/erp'
|
||||||
|
|
||||||
const SalesTeamCreate: React.FC = () => {
|
const SalesTeamCreate: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
@ -308,9 +309,11 @@ const SalesTeamCreate: React.FC = () => {
|
||||||
onChange={(e) => updateMember(index, 'role', e.target.value)}
|
onChange={(e) => updateMember(index, 'role', e.target.value)}
|
||||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
{Object.values(TeamRoleEnum).map((role) => (
|
||||||
<option value={TeamRoleEnum.Lead}>Takım Lideri</option>
|
<option key={role} value={role}>
|
||||||
<option value={TeamRoleEnum.Manager}>Yönetici</option>
|
{getTeamRoleText(role)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { getTeamRoleText } from '@/utils/erp'
|
||||||
|
|
||||||
const SalesTeamEdit: React.FC = () => {
|
const SalesTeamEdit: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
@ -358,9 +359,11 @@ const SalesTeamEdit: React.FC = () => {
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
{Object.values(TeamRoleEnum).map((role) => (
|
||||||
<option value={TeamRoleEnum.Lead}>Takım Lideri</option>
|
<option key={role} value={role}>
|
||||||
<option value={TeamRoleEnum.Manager}>Yönetici</option>
|
{getTeamRoleText(role)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,7 @@ export function ForumView({
|
||||||
: 'hover:text-blue-600 cursor-pointer'
|
: 'hover:text-blue-600 cursor-pointer'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Forum
|
<h2 className="text-2xl font-bold text-gray-900">Forum</h2>
|
||||||
</button>
|
</button>
|
||||||
{selectedCategory && (
|
{selectedCategory && (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaSave, FaTimes } from "react-icons/fa";
|
import { FaSave, FaTimes } from 'react-icons/fa'
|
||||||
import { HrCostCenter, CostCenterType } from "../../../types/hr";
|
import { HrCostCenter, CostCenterType } from '../../../types/hr'
|
||||||
import { mockEmployees } from "../../../mocks/mockEmployees";
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { mockCostCenters } from "../../../mocks/mockCostCenters";
|
import { mockCostCenters } from '../../../mocks/mockCostCenters'
|
||||||
import { getCostCenterTypeText } from "../../../utils/erp";
|
import { getCostCenterTypeText } from '../../../utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
interface CostCenterFormModalProps {
|
interface CostCenterFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (costCenter: Partial<HrCostCenter>) => void;
|
onSave: (costCenter: Partial<HrCostCenter>) => void
|
||||||
costCenter?: HrCostCenter;
|
costCenter?: HrCostCenter
|
||||||
title: string;
|
title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
|
|
@ -21,55 +22,55 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
title,
|
title,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
costCenterCode: "",
|
costCenterCode: '',
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
costCenterType: CostCenterType.Standard,
|
costCenterType: CostCenterType.Standard,
|
||||||
responsibleEmployeeId: "",
|
responsibleEmployeeId: '',
|
||||||
parentCostCenterId: "",
|
parentCostCenterId: '',
|
||||||
budgetedAmount: 0,
|
budgetedAmount: 0,
|
||||||
actualAmount: 0,
|
actualAmount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
fiscalYear: "2025",
|
fiscalYear: '2025',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (costCenter) {
|
if (costCenter) {
|
||||||
setFormData({
|
setFormData({
|
||||||
costCenterCode: costCenter.code,
|
costCenterCode: costCenter.code,
|
||||||
name: costCenter.name,
|
name: costCenter.name,
|
||||||
description: costCenter.description || "",
|
description: costCenter.description || '',
|
||||||
costCenterType: costCenter.costCenterType,
|
costCenterType: costCenter.costCenterType,
|
||||||
responsibleEmployeeId: costCenter.responsibleEmployeeId || "",
|
responsibleEmployeeId: costCenter.responsibleEmployeeId || '',
|
||||||
parentCostCenterId: costCenter.parentCostCenterId || "",
|
parentCostCenterId: costCenter.parentCostCenterId || '',
|
||||||
budgetedAmount: costCenter.budgetedAmount,
|
budgetedAmount: costCenter.budgetedAmount,
|
||||||
actualAmount: costCenter.actualAmount,
|
actualAmount: costCenter.actualAmount,
|
||||||
currency: costCenter.currency,
|
currency: costCenter.currency,
|
||||||
fiscalYear: costCenter.fiscalYear,
|
fiscalYear: costCenter.fiscalYear,
|
||||||
isActive: costCenter.isActive,
|
isActive: costCenter.isActive,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
costCenterCode: "",
|
costCenterCode: '',
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
costCenterType: CostCenterType.Standard,
|
costCenterType: CostCenterType.Standard,
|
||||||
responsibleEmployeeId: "",
|
responsibleEmployeeId: '',
|
||||||
parentCostCenterId: "",
|
parentCostCenterId: '',
|
||||||
budgetedAmount: 0,
|
budgetedAmount: 0,
|
||||||
actualAmount: 0,
|
actualAmount: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
fiscalYear: "2025",
|
fiscalYear: '2025',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}, [costCenter]);
|
}, [costCenter])
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
onSave(formData);
|
onSave(formData)
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
isOpen && (
|
isOpen && (
|
||||||
|
|
@ -77,10 +78,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
<div className="bg-white rounded-lg p-3 w-full max-w-lg max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg p-3 w-full max-w-lg max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<h2 className="text-base font-bold text-gray-900">{title}</h2>
|
<h2 className="text-base font-bold text-gray-900">{title}</h2>
|
||||||
<button
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5" />
|
<FaTimes className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -94,9 +92,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.costCenterCode}
|
value={formData.costCenterCode}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, costCenterCode: e.target.value })}
|
||||||
setFormData({ ...formData, costCenterCode: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
@ -109,9 +105,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.name}
|
value={formData.name}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||||
setFormData({ ...formData, name: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
@ -119,14 +113,10 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Açıklama</label>
|
||||||
Açıklama
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.description}
|
value={formData.description}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||||
setFormData({ ...formData, description: e.target.value })
|
|
||||||
}
|
|
||||||
rows={2}
|
rows={2}
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
|
|
@ -206,15 +196,11 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Mali Yıl</label>
|
||||||
Mali Yıl
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.fiscalYear}
|
value={formData.fiscalYear}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, fiscalYear: e.target.value })}
|
||||||
setFormData({ ...formData, fiscalYear: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -222,9 +208,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Bütçe Tutarı</label>
|
||||||
Bütçe Tutarı
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={formData.budgetedAmount}
|
value={formData.budgetedAmount}
|
||||||
|
|
@ -256,19 +240,17 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||||
Para Birimi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currency}
|
value={formData.currency}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, currency: e.target.value })}
|
||||||
setFormData({ ...formData, currency: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -277,9 +259,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={formData.isActive}
|
checked={formData.isActive}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, isActive: e.target.checked })}
|
||||||
setFormData({ ...formData, isActive: e.target.checked })
|
|
||||||
}
|
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<label className="ml-2 block text-sm text-gray-900">Aktif</label>
|
<label className="ml-2 block text-sm text-gray-900">Aktif</label>
|
||||||
|
|
@ -305,7 +285,7 @@ const CostCenterFormModal: React.FC<CostCenterFormModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CostCenterFormModal;
|
export default CostCenterFormModal
|
||||||
|
|
|
||||||
|
|
@ -808,9 +808,11 @@ const Degree360Evaluation: React.FC = () => {
|
||||||
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
|
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={CampaignStatusEnum.Draft}>Taslak</option>
|
{Object.values(CampaignStatusEnum).map((status) => (
|
||||||
<option value={CampaignStatusEnum.Active}>Aktif</option>
|
<option key={status} value={status}>
|
||||||
<option value={CampaignStatusEnum.Completed}>Tamamlandı</option>
|
{getCampaignStatusText(status)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
@ -834,7 +836,7 @@ const Degree360Evaluation: React.FC = () => {
|
||||||
<option value="all">Tüm Personel</option>
|
<option value="all">Tüm Personel</option>
|
||||||
{mockEmployees.map((employee) => (
|
{mockEmployees.map((employee) => (
|
||||||
<option key={employee.id} value={employee.id}>
|
<option key={employee.id} value={employee.id}>
|
||||||
{employee.firstName} {employee.lastName}
|
{employee.fullName}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -887,11 +889,11 @@ const Degree360Evaluation: React.FC = () => {
|
||||||
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
|
className="border border-gray-300 rounded-md px-2.5 py-1 text-sm"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={ParticipantStatusEnum.Invited}>Davet Edildi</option>
|
{Object.values(ParticipantStatusEnum).map((status) => (
|
||||||
<option value={ParticipantStatusEnum.Started}>Başladı</option>
|
<option key={status} value={status}>
|
||||||
<option value={ParticipantStatusEnum.Completed}>Tamamlandı</option>
|
{getParticipantStatusText(status)}
|
||||||
<option value={ParticipantStatusEnum.Expired}>Süresi Dolmuş</option>
|
</option>
|
||||||
<option value={ParticipantStatusEnum.Declined}>Reddedildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
QuestionTypeEnum,
|
QuestionTypeEnum,
|
||||||
HrQuestionOption,
|
HrQuestionOption,
|
||||||
AssessorTypeEnum,
|
AssessorTypeEnum,
|
||||||
|
getQuestionTypeText,
|
||||||
} from '../../../types/hr'
|
} from '../../../types/hr'
|
||||||
import DataTable, { Column } from '../../../components/common/DataTable'
|
import DataTable, { Column } from '../../../components/common/DataTable'
|
||||||
import { mockEvaluation360Templates } from '../../../mocks/mockEvaluation360Templates'
|
import { mockEvaluation360Templates } from '../../../mocks/mockEvaluation360Templates'
|
||||||
|
|
@ -692,10 +693,11 @@ const Degree360Templates: React.FC = () => {
|
||||||
}
|
}
|
||||||
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
|
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
|
||||||
>
|
>
|
||||||
<option value={QuestionTypeEnum.Rating}>Puanlama</option>
|
{Object.values(QuestionTypeEnum).map((type) => (
|
||||||
<option value={QuestionTypeEnum.MultipleChoice}>Çoktan Seçmeli</option>
|
<option key={type} value={type}>
|
||||||
<option value={QuestionTypeEnum.Text}>Metin</option>
|
{getQuestionTypeText(type)}
|
||||||
<option value={QuestionTypeEnum.YesNo}>Evet/Hayır</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,11 @@ const EmployeeCards: React.FC = () => {
|
||||||
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={EmployeeStatusEnum.Active}>Aktif</option>
|
{Object.values(EmployeeStatusEnum).map((status) => (
|
||||||
<option value={EmployeeStatusEnum.Inactive}>Pasif</option>
|
<option key={status} value={status}>
|
||||||
<option value={EmployeeStatusEnum.OnLeave}>İzinli</option>
|
{getEmployeeStatusText(status)}
|
||||||
<option value={EmployeeStatusEnum.Suspended}>Askıda</option>
|
</option>
|
||||||
<option value={EmployeeStatusEnum.Terminated}>İşten Çıkarılmış</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,15 @@ import {
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
import {
|
||||||
|
getEmployeeStatusText,
|
||||||
|
getEmploymentTypeText,
|
||||||
|
getFrequencyUnitText,
|
||||||
|
getGenderText,
|
||||||
|
getMaritalStatusText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
import { FrequencyUnitEnum } from '@/types/pm'
|
||||||
|
|
||||||
interface ValidationErrors {
|
interface ValidationErrors {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
|
|
@ -370,8 +379,11 @@ const EmployeeForm: React.FC = () => {
|
||||||
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Cinsiyet seçin</option>
|
<option value="">Cinsiyet seçin</option>
|
||||||
<option value="MALE">Erkek</option>
|
{Object.values(GenderEnum).map((gender) => (
|
||||||
<option value="FEMALE">Kadın</option>
|
<option key={gender} value={gender}>
|
||||||
|
{getGenderText(gender)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -385,10 +397,11 @@ const EmployeeForm: React.FC = () => {
|
||||||
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Medeni durum seçin</option>
|
<option value="">Medeni durum seçin</option>
|
||||||
<option value="SINGLE">Bekar</option>
|
{Object.values(MaritalStatusEnum).map((status) => (
|
||||||
<option value="MARRIED">Evli</option>
|
<option key={status} value={status}>
|
||||||
<option value="DIVORCED">Boşanmış</option>
|
{getMaritalStatusText(status)}
|
||||||
<option value="WIDOWED">Dul</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -508,11 +521,11 @@ const EmployeeForm: React.FC = () => {
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value="">Tip seçin</option>
|
<option value="">Tip seçin</option>
|
||||||
<option value="FULL_TIME">Tam Zamanlı</option>
|
{Object.values(EmploymentTypeEnum).map((type) => (
|
||||||
<option value="PART_TIME">Yarı Zamanlı</option>
|
<option key={type} value={type}>
|
||||||
<option value="CONTRACT">Sözleşmeli</option>
|
{getEmploymentTypeText(type)}
|
||||||
<option value="INTERN">Stajyer</option>
|
</option>
|
||||||
<option value="TEMPORARY">Geçici</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.employmentType && (
|
{errors.employmentType && (
|
||||||
<p className="mt-1 text-sm text-red-600">{errors.employmentType}</p>
|
<p className="mt-1 text-sm text-red-600">{errors.employmentType}</p>
|
||||||
|
|
@ -660,9 +673,11 @@ const EmployeeForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">Türk Lirası (TRY)</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">Amerikan Doları (USD)</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">Euro (EUR)</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -676,9 +691,15 @@ const EmployeeForm: React.FC = () => {
|
||||||
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Grup seçin</option>
|
<option value="">Grup seçin</option>
|
||||||
<option value="MONTHLY">Aylık</option>
|
<option value={FrequencyUnitEnum.Weeks}>
|
||||||
<option value="WEEKLY">Haftalık</option>
|
{getFrequencyUnitText(FrequencyUnitEnum.Weeks)}
|
||||||
<option value="HOURLY">Saatlik</option>
|
</option>
|
||||||
|
<option value={FrequencyUnitEnum.Months}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Months)}
|
||||||
|
</option>
|
||||||
|
<option value={FrequencyUnitEnum.Hours}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Hours)}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -748,10 +769,11 @@ const EmployeeForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('employeeStatus', e.target.value)}
|
onChange={(e) => handleInputChange('employeeStatus', e.target.value)}
|
||||||
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="ACTIVE">Aktif</option>
|
{Object.values(EmployeeStatusEnum).map((status) => (
|
||||||
<option value="INACTIVE">Pasif</option>
|
<option key={status} value={status}>
|
||||||
<option value="ON_LEAVE">İzinli</option>
|
{getEmployeeStatusText(status)}
|
||||||
<option value="TERMINATED">İşten Ayrılmış</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,12 @@ import {
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { mockDepartments } from '@/mocks/mockDepartments'
|
||||||
|
|
||||||
const EmployeeList: React.FC = () => {
|
const EmployeeList: React.FC = () => {
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [filterStatus, setFilterStatus] = useState('all')
|
const [filterStatus, setFilterStatus] = useState('all')
|
||||||
const [filterDepartment, setFilterDepartment] = useState('all')
|
const [filterDepartment, setFilterDepartment] = useState('')
|
||||||
const [showFilters, setShowFilters] = useState(false)
|
const [showFilters, setShowFilters] = useState(false)
|
||||||
const [viewMode, setViewMode] = useState<'list' | 'cards'>('list')
|
const [viewMode, setViewMode] = useState<'list' | 'cards'>('list')
|
||||||
|
|
||||||
|
|
@ -204,11 +205,11 @@ const EmployeeList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={EmployeeStatusEnum.Active}>Aktif</option>
|
{Object.values(EmployeeStatusEnum).map((status) => (
|
||||||
<option value={EmployeeStatusEnum.Inactive}>Pasif</option>
|
<option key={status} value={status}>
|
||||||
<option value={EmployeeStatusEnum.OnLeave}>İzinli</option>
|
{getEmployeeStatusText(status)}
|
||||||
<option value={EmployeeStatusEnum.Suspended}>Askıda</option>
|
</option>
|
||||||
<option value={EmployeeStatusEnum.Terminated}>İşten Çıkarıldı</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -220,10 +221,11 @@ const EmployeeList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value="IT">Bilgi İşlem</option>
|
{mockDepartments.map((dept) => (
|
||||||
<option value="PROC">Satınalma</option>
|
<option key={dept.id} value={dept.id}>
|
||||||
<option value="PROD">Üretim</option>
|
{dept.name}
|
||||||
<option value="HR">İnsan Kaynakları</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaSave, FaTimes, FaPlus, FaTrash } from "react-icons/fa";
|
import { FaSave, FaTimes, FaPlus, FaTrash } from 'react-icons/fa'
|
||||||
import { HrJobPosition, JobLevelEnum } from "../../../types/hr";
|
import { HrJobPosition, JobLevelEnum } from '../../../types/hr'
|
||||||
import { mockDepartments } from "../../../mocks/mockDepartments";
|
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||||
|
import { getJobLevelText } from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
interface JobPositionFormModalProps {
|
interface JobPositionFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (position: Partial<HrJobPosition>) => void;
|
onSave: (position: Partial<HrJobPosition>) => void
|
||||||
position?: HrJobPosition;
|
position?: HrJobPosition
|
||||||
title: string;
|
title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
|
|
@ -19,31 +21,31 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
title,
|
title,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
positionCode: "",
|
positionCode: '',
|
||||||
title: "",
|
title: '',
|
||||||
description: "",
|
description: '',
|
||||||
departmentId: "",
|
departmentId: '',
|
||||||
level: JobLevelEnum.Entry,
|
level: JobLevelEnum.Entry,
|
||||||
minSalary: 0,
|
minSalary: 0,
|
||||||
maxSalary: 0,
|
maxSalary: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
requiredSkills: [] as string[],
|
requiredSkills: [] as string[],
|
||||||
responsibilities: [] as string[],
|
responsibilities: [] as string[],
|
||||||
qualifications: [] as string[],
|
qualifications: [] as string[],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
||||||
const [skillInput, setSkillInput] = useState("");
|
const [skillInput, setSkillInput] = useState('')
|
||||||
const [responsibilityInput, setResponsibilityInput] = useState("");
|
const [responsibilityInput, setResponsibilityInput] = useState('')
|
||||||
const [qualificationInput, setQualificationInput] = useState("");
|
const [qualificationInput, setQualificationInput] = useState('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (position) {
|
if (position) {
|
||||||
setFormData({
|
setFormData({
|
||||||
positionCode: position.code,
|
positionCode: position.code,
|
||||||
title: position.name,
|
title: position.name,
|
||||||
description: position.description || "",
|
description: position.description || '',
|
||||||
departmentId: position.departmentId,
|
departmentId: position.departmentId,
|
||||||
level: position.level,
|
level: position.level,
|
||||||
minSalary: position.minSalary,
|
minSalary: position.minSalary,
|
||||||
|
|
@ -53,97 +55,91 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
responsibilities: [...(position.responsibilities || [])],
|
responsibilities: [...(position.responsibilities || [])],
|
||||||
qualifications: [...(position.qualifications || [])],
|
qualifications: [...(position.qualifications || [])],
|
||||||
isActive: position.isActive,
|
isActive: position.isActive,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData({
|
setFormData({
|
||||||
positionCode: "",
|
positionCode: '',
|
||||||
title: "",
|
title: '',
|
||||||
description: "",
|
description: '',
|
||||||
departmentId: "",
|
departmentId: '',
|
||||||
level: JobLevelEnum.Entry,
|
level: JobLevelEnum.Entry,
|
||||||
minSalary: 0,
|
minSalary: 0,
|
||||||
maxSalary: 0,
|
maxSalary: 0,
|
||||||
currency: "TRY",
|
currency: 'TRY',
|
||||||
requiredSkills: [],
|
requiredSkills: [],
|
||||||
responsibilities: [],
|
responsibilities: [],
|
||||||
qualifications: [],
|
qualifications: [],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setErrors({});
|
setErrors({})
|
||||||
setSkillInput("");
|
setSkillInput('')
|
||||||
setResponsibilityInput("");
|
setResponsibilityInput('')
|
||||||
setQualificationInput("");
|
setQualificationInput('')
|
||||||
}, [position, isOpen]);
|
}, [position, isOpen])
|
||||||
|
|
||||||
const validateForm = (): boolean => {
|
const validateForm = (): boolean => {
|
||||||
const newErrors: Record<string, string> = {};
|
const newErrors: Record<string, string> = {}
|
||||||
|
|
||||||
if (!formData.positionCode.trim()) {
|
if (!formData.positionCode.trim()) {
|
||||||
newErrors.positionCode = "Pozisyon kodu zorunludur";
|
newErrors.positionCode = 'Pozisyon kodu zorunludur'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.title.trim()) {
|
if (!formData.title.trim()) {
|
||||||
newErrors.title = "Pozisyon adı zorunludur";
|
newErrors.title = 'Pozisyon adı zorunludur'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.departmentId) {
|
if (!formData.departmentId) {
|
||||||
newErrors.departmentId = "Departman seçimi zorunludur";
|
newErrors.departmentId = 'Departman seçimi zorunludur'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.minSalary < 0) {
|
if (formData.minSalary < 0) {
|
||||||
newErrors.minSalary = "Minimum maaş negatif olamaz";
|
newErrors.minSalary = 'Minimum maaş negatif olamaz'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.maxSalary < 0) {
|
if (formData.maxSalary < 0) {
|
||||||
newErrors.maxSalary = "Maksimum maaş negatif olamaz";
|
newErrors.maxSalary = 'Maksimum maaş negatif olamaz'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.maxSalary < formData.minSalary) {
|
if (formData.maxSalary < formData.minSalary) {
|
||||||
newErrors.maxSalary = "Maksimum maaş minimum maaştan düşük olamaz";
|
newErrors.maxSalary = 'Maksimum maaş minimum maaştan düşük olamaz'
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors)
|
||||||
return Object.keys(newErrors).length === 0;
|
return Object.keys(newErrors).length === 0
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
onSave(formData);
|
onSave(formData)
|
||||||
onClose();
|
onClose()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (field: string, value: string | number | boolean | JobLevelEnum) => {
|
||||||
field: string,
|
|
||||||
value: string | number | boolean | JobLevelEnum
|
|
||||||
) => {
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[field]: value,
|
[field]: value,
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const addSkill = () => {
|
const addSkill = () => {
|
||||||
if (
|
if (skillInput.trim() && !formData.requiredSkills.includes(skillInput.trim())) {
|
||||||
skillInput.trim() &&
|
|
||||||
!formData.requiredSkills.includes(skillInput.trim())
|
|
||||||
) {
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
requiredSkills: [...prev.requiredSkills, skillInput.trim()],
|
requiredSkills: [...prev.requiredSkills, skillInput.trim()],
|
||||||
}));
|
}))
|
||||||
setSkillInput("");
|
setSkillInput('')
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const removeSkill = (index: number) => {
|
const removeSkill = (index: number) => {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
requiredSkills: prev.requiredSkills.filter((_, i) => i !== index),
|
requiredSkills: prev.requiredSkills.filter((_, i) => i !== index),
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const addResponsibility = () => {
|
const addResponsibility = () => {
|
||||||
if (
|
if (
|
||||||
|
|
@ -152,53 +148,44 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
) {
|
) {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
responsibilities: [
|
responsibilities: [...prev.responsibilities, responsibilityInput.trim()],
|
||||||
...prev.responsibilities,
|
}))
|
||||||
responsibilityInput.trim(),
|
setResponsibilityInput('')
|
||||||
],
|
|
||||||
}));
|
|
||||||
setResponsibilityInput("");
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const removeResponsibility = (index: number) => {
|
const removeResponsibility = (index: number) => {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
responsibilities: prev.responsibilities.filter((_, i) => i !== index),
|
responsibilities: prev.responsibilities.filter((_, i) => i !== index),
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const addQualification = () => {
|
const addQualification = () => {
|
||||||
if (
|
if (qualificationInput.trim() && !formData.qualifications.includes(qualificationInput.trim())) {
|
||||||
qualificationInput.trim() &&
|
|
||||||
!formData.qualifications.includes(qualificationInput.trim())
|
|
||||||
) {
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
qualifications: [...prev.qualifications, qualificationInput.trim()],
|
qualifications: [...prev.qualifications, qualificationInput.trim()],
|
||||||
}));
|
}))
|
||||||
setQualificationInput("");
|
setQualificationInput('')
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const removeQualification = (index: number) => {
|
const removeQualification = (index: number) => {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
qualifications: prev.qualifications.filter((_, i) => i !== index),
|
qualifications: prev.qualifications.filter((_, i) => i !== index),
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
|
||||||
<div className="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-3 border-b">
|
<div className="flex items-center justify-between p-3 border-b">
|
||||||
<h2 className="text-xl font-bold text-gray-900">{title}</h2>
|
<h2 className="text-xl font-bold text-gray-900">{title}</h2>
|
||||||
<button
|
<button onClick={onClose} className="p-1 hover:bg-gray-100 rounded-full">
|
||||||
onClick={onClose}
|
|
||||||
className="p-1 hover:bg-gray-100 rounded-full"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5" />
|
<FaTimes className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -214,47 +201,37 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.positionCode}
|
value={formData.positionCode}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('positionCode', e.target.value)}
|
||||||
handleInputChange("positionCode", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.positionCode ? "border-red-500" : "border-gray-300"
|
errors.positionCode ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Örn: DEV-001"
|
placeholder="Örn: DEV-001"
|
||||||
/>
|
/>
|
||||||
{errors.positionCode && (
|
{errors.positionCode && (
|
||||||
<p className="text-red-500 text-sm mt-1">
|
<p className="text-red-500 text-sm mt-1">{errors.positionCode}</p>
|
||||||
{errors.positionCode}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Pozisyon Adı *</label>
|
||||||
Pozisyon Adı *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.title}
|
value={formData.title}
|
||||||
onChange={(e) => handleInputChange("title", e.target.value)}
|
onChange={(e) => handleInputChange('title', e.target.value)}
|
||||||
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.title ? "border-red-500" : "border-gray-300"
|
errors.title ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
placeholder="Örn: Software Developer"
|
placeholder="Örn: Software Developer"
|
||||||
/>
|
/>
|
||||||
{errors.title && (
|
{errors.title && <p className="text-red-500 text-sm mt-1">{errors.title}</p>}
|
||||||
<p className="text-red-500 text-sm mt-1">{errors.title}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Açıklama</label>
|
||||||
Açıklama
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.description}
|
value={formData.description}
|
||||||
onChange={(e) => handleInputChange("description", e.target.value)}
|
onChange={(e) => handleInputChange('description', e.target.value)}
|
||||||
rows={2}
|
rows={2}
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Pozisyon açıklaması..."
|
placeholder="Pozisyon açıklaması..."
|
||||||
|
|
@ -263,16 +240,12 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Departman *</label>
|
||||||
Departman *
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.departmentId}
|
value={formData.departmentId}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('departmentId', e.target.value)}
|
||||||
handleInputChange("departmentId", e.target.value)
|
|
||||||
}
|
|
||||||
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.departmentId ? "border-red-500" : "border-gray-300"
|
errors.departmentId ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value="">Departman seçin</option>
|
<option value="">Departman seçin</option>
|
||||||
|
|
@ -283,33 +256,22 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.departmentId && (
|
{errors.departmentId && (
|
||||||
<p className="text-red-500 text-sm mt-1">
|
<p className="text-red-500 text-sm mt-1">{errors.departmentId}</p>
|
||||||
{errors.departmentId}
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Seviye</label>
|
||||||
Seviye
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.level}
|
value={formData.level}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('level', e.target.value as JobLevelEnum)}
|
||||||
handleInputChange("level", e.target.value as JobLevelEnum)
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={JobLevelEnum.Entry}>Giriş Seviyesi</option>
|
{Object.values(JobLevelEnum).map((level) => (
|
||||||
<option value={JobLevelEnum.Junior}>Junior</option>
|
<option key={level} value={level}>
|
||||||
<option value={JobLevelEnum.Mid}>Orta Seviye</option>
|
{getJobLevelText(level)}
|
||||||
<option value={JobLevelEnum.Senior}>Senior</option>
|
</option>
|
||||||
<option value={JobLevelEnum.Lead}>Lider</option>
|
))}
|
||||||
<option value={JobLevelEnum.Manager}>Yönetici</option>
|
|
||||||
<option value={JobLevelEnum.Director}>Direktör</option>
|
|
||||||
<option value={JobLevelEnum.Executive}>
|
|
||||||
Üst Düzey Yönetici
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -317,23 +279,17 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
{/* Salary Information */}
|
{/* Salary Information */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Minimum Maaş *</label>
|
||||||
Minimum Maaş *
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={formData.minSalary}
|
value={formData.minSalary}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('minSalary', Number(e.target.value))}
|
||||||
handleInputChange("minSalary", Number(e.target.value))
|
|
||||||
}
|
|
||||||
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.minSalary ? "border-red-500" : "border-gray-300"
|
errors.minSalary ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
{errors.minSalary && (
|
{errors.minSalary && <p className="text-red-500 text-sm mt-1">{errors.minSalary}</p>}
|
||||||
<p className="text-red-500 text-sm mt-1">{errors.minSalary}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -343,31 +299,27 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={formData.maxSalary}
|
value={formData.maxSalary}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('maxSalary', Number(e.target.value))}
|
||||||
handleInputChange("maxSalary", Number(e.target.value))
|
|
||||||
}
|
|
||||||
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-2 py-1 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||||
errors.maxSalary ? "border-red-500" : "border-gray-300"
|
errors.maxSalary ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
{errors.maxSalary && (
|
{errors.maxSalary && <p className="text-red-500 text-sm mt-1">{errors.maxSalary}</p>}
|
||||||
<p className="text-red-500 text-sm mt-1">{errors.maxSalary}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Para Birimi</label>
|
||||||
Para Birimi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.currency}
|
value={formData.currency}
|
||||||
onChange={(e) => handleInputChange("currency", e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -382,9 +334,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
type="text"
|
type="text"
|
||||||
value={skillInput}
|
value={skillInput}
|
||||||
onChange={(e) => setSkillInput(e.target.value)}
|
onChange={(e) => setSkillInput(e.target.value)}
|
||||||
onKeyPress={(e) =>
|
onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), addSkill())}
|
||||||
e.key === "Enter" && (e.preventDefault(), addSkill())
|
|
||||||
}
|
|
||||||
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Yetenek ekleyin..."
|
placeholder="Yetenek ekleyin..."
|
||||||
/>
|
/>
|
||||||
|
|
@ -417,17 +367,13 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
|
|
||||||
{/* Responsibilities */}
|
{/* Responsibilities */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Sorumluluklar</label>
|
||||||
Sorumluluklar
|
|
||||||
</label>
|
|
||||||
<div className="flex gap-2 mb-2">
|
<div className="flex gap-2 mb-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={responsibilityInput}
|
value={responsibilityInput}
|
||||||
onChange={(e) => setResponsibilityInput(e.target.value)}
|
onChange={(e) => setResponsibilityInput(e.target.value)}
|
||||||
onKeyPress={(e) =>
|
onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), addResponsibility())}
|
||||||
e.key === "Enter" && (e.preventDefault(), addResponsibility())
|
|
||||||
}
|
|
||||||
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Sorumluluk ekleyin..."
|
placeholder="Sorumluluk ekleyin..."
|
||||||
/>
|
/>
|
||||||
|
|
@ -445,9 +391,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
key={index}
|
key={index}
|
||||||
className="flex items-center justify-between p-2 bg-green-50 rounded-md text-sm"
|
className="flex items-center justify-between p-2 bg-green-50 rounded-md text-sm"
|
||||||
>
|
>
|
||||||
<span className="text-green-800 text-sm">
|
<span className="text-green-800 text-sm">{responsibility}</span>
|
||||||
{responsibility}
|
|
||||||
</span>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => removeResponsibility(index)}
|
onClick={() => removeResponsibility(index)}
|
||||||
|
|
@ -462,17 +406,13 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
|
|
||||||
{/* Qualifications */}
|
{/* Qualifications */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<label className="block text-xs font-medium text-gray-700 mb-1">Nitelikler</label>
|
||||||
Nitelikler
|
|
||||||
</label>
|
|
||||||
<div className="flex gap-2 mb-2">
|
<div className="flex gap-2 mb-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={qualificationInput}
|
value={qualificationInput}
|
||||||
onChange={(e) => setQualificationInput(e.target.value)}
|
onChange={(e) => setQualificationInput(e.target.value)}
|
||||||
onKeyPress={(e) =>
|
onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), addQualification())}
|
||||||
e.key === "Enter" && (e.preventDefault(), addQualification())
|
|
||||||
}
|
|
||||||
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Nitelik ekleyin..."
|
placeholder="Nitelik ekleyin..."
|
||||||
/>
|
/>
|
||||||
|
|
@ -490,9 +430,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
key={index}
|
key={index}
|
||||||
className="flex items-center justify-between p-2 bg-purple-50 rounded-md text-sm"
|
className="flex items-center justify-between p-2 bg-purple-50 rounded-md text-sm"
|
||||||
>
|
>
|
||||||
<span className="text-purple-800 text-sm">
|
<span className="text-purple-800 text-sm">{qualification}</span>
|
||||||
{qualification}
|
|
||||||
</span>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => removeQualification(index)}
|
onClick={() => removeQualification(index)}
|
||||||
|
|
@ -511,13 +449,10 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="isActive"
|
id="isActive"
|
||||||
checked={formData.isActive}
|
checked={formData.isActive}
|
||||||
onChange={(e) => handleInputChange("isActive", e.target.checked)}
|
onChange={(e) => handleInputChange('isActive', e.target.checked)}
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<label
|
<label htmlFor="isActive" className="ml-2 block text-sm text-gray-900">
|
||||||
htmlFor="isActive"
|
|
||||||
className="ml-2 block text-sm text-gray-900"
|
|
||||||
>
|
|
||||||
Aktif pozisyon
|
Aktif pozisyon
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -543,7 +478,7 @@ const JobPositionFormModal: React.FC<JobPositionFormModalProps> = ({
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default JobPositionFormModal;
|
export default JobPositionFormModal
|
||||||
|
|
|
||||||
|
|
@ -336,9 +336,7 @@ const JobPositions: React.FC = () => {
|
||||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900">İş Pozisyonları</h2>
|
<h2 className="text-2xl font-bold text-gray-900">İş Pozisyonları</h2>
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600">Şirket pozisyonları ve iş tanımları yönetimi</p>
|
||||||
Şirket pozisyonları ve iş tanımları yönetimi
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{/* View Toggle */}
|
{/* View Toggle */}
|
||||||
|
|
@ -442,14 +440,11 @@ const JobPositions: React.FC = () => {
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 min-w-0 sm:min-w-[160px]"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 min-w-0 sm:min-w-[160px]"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Seviyeler</option>
|
<option value="all">Tüm Seviyeler</option>
|
||||||
<option value={JobLevelEnum.Entry}>Giriş Seviyesi</option>
|
{Object.values(JobLevelEnum).map((level) => (
|
||||||
<option value={JobLevelEnum.Junior}>Junior</option>
|
<option key={level} value={level}>
|
||||||
<option value={JobLevelEnum.Mid}>Orta Seviye</option>
|
{getJobLevelText(level)}
|
||||||
<option value={JobLevelEnum.Senior}>Senior</option>
|
</option>
|
||||||
<option value={JobLevelEnum.Lead}>Lider</option>
|
))}
|
||||||
<option value={JobLevelEnum.Manager}>Yönetici</option>
|
|
||||||
<option value={JobLevelEnum.Director}>Direktör</option>
|
|
||||||
<option value={JobLevelEnum.Executive}>Üst Düzey Yönetici</option>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
|
||||||
|
|
@ -506,10 +506,11 @@ const LeaveManagement: React.FC = () => {
|
||||||
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={LeaveStatusEnum.Pending}>Beklemede</option>
|
{Object.values(LeaveStatusEnum).map((status) => (
|
||||||
<option value={LeaveStatusEnum.Approved}>Onaylandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={LeaveStatusEnum.Rejected}>Reddedildi</option>
|
{getLeaveStatusText(status)}
|
||||||
<option value={LeaveStatusEnum.Cancelled}>İptal Edildi</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
@ -518,14 +519,11 @@ const LeaveManagement: React.FC = () => {
|
||||||
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm İzin Türleri</option>
|
<option value="all">Tüm İzin Türleri</option>
|
||||||
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option>
|
{Object.values(LeaveTypeEnum).map((type) => (
|
||||||
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option>
|
<option key={type} value={type}>
|
||||||
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option>
|
{getLeaveTypeText(type)}
|
||||||
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</option>
|
</option>
|
||||||
<option value={LeaveTypeEnum.Personal}>Kişisel İzin</option>
|
))}
|
||||||
<option value={LeaveTypeEnum.Emergency}>Acil Durum İzni</option>
|
|
||||||
<option value={LeaveTypeEnum.Study}>Eğitim İzni</option>
|
|
||||||
<option value={LeaveTypeEnum.Unpaid}>Ücretsiz İzin</option>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
@ -591,14 +589,11 @@ const LeaveManagement: React.FC = () => {
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option>
|
{Object.values(LeaveTypeEnum).map((type) => (
|
||||||
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option>
|
<option key={type} value={type}>
|
||||||
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option>
|
{getLeaveTypeText(type)}
|
||||||
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</option>
|
</option>
|
||||||
<option value={LeaveTypeEnum.Personal}>Kişisel İzin</option>
|
))}
|
||||||
<option value={LeaveTypeEnum.Emergency}>Acil Durum İzni</option>
|
|
||||||
<option value={LeaveTypeEnum.Study}>Eğitim İzni</option>
|
|
||||||
<option value={LeaveTypeEnum.Unpaid}>Ücretsiz İzin</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -933,14 +928,11 @@ const LeaveManagement: React.FC = () => {
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={LeaveTypeEnum.Annual}>Yıllık İzin</option>
|
{Object.values(LeaveStatusEnum).map((status) => (
|
||||||
<option value={LeaveTypeEnum.Sick}>Hastalık İzni</option>
|
<option key={status} value={status}>
|
||||||
<option value={LeaveTypeEnum.Maternity}>Doğum İzni</option>
|
{getLeaveStatusText(status)}
|
||||||
<option value={LeaveTypeEnum.Paternity}>Babalık İzni</option>
|
</option>
|
||||||
<option value={LeaveTypeEnum.Personal}>Kişisel İzin</option>
|
))}
|
||||||
<option value={LeaveTypeEnum.Emergency}>Acil Durum İzni</option>
|
|
||||||
<option value={LeaveTypeEnum.Study}>Eğitim İzni</option>
|
|
||||||
<option value={LeaveTypeEnum.Unpaid}>Ücretsiz İzin</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -544,9 +544,11 @@ const OvertimeManagement: React.FC = () => {
|
||||||
className="border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={LeaveStatusEnum.Pending}>Beklemede</option>
|
{Object.values(LeaveStatusEnum).map((status) => (
|
||||||
<option value={LeaveStatusEnum.Approved}>Onaylı</option>
|
<option key={status} value={status}>
|
||||||
<option value={LeaveStatusEnum.Rejected}>Reddedildi</option>
|
{getLeaveStatusText(status)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
|
||||||
|
|
@ -515,11 +515,11 @@ const PayrollManagement: React.FC = () => {
|
||||||
className="px-3 py-1.5 border border-gray-300 text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="px-3 py-1.5 border border-gray-300 text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={PayrollStatusEnum.Draft}>Taslak</option>
|
{Object.values(PayrollStatusEnum).map((status) => (
|
||||||
<option value={PayrollStatusEnum.Calculated}>Hesaplandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={PayrollStatusEnum.Approved}>Onaylandı</option>
|
{getPayrollStatusText(status)}
|
||||||
<option value={PayrollStatusEnum.Paid}>Ödendi</option>
|
</option>
|
||||||
<option value={PayrollStatusEnum.Cancelled}>İptal Edildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
|
||||||
|
|
@ -137,12 +137,21 @@ const ChangeNotificationStatusModal: React.FC<ChangeNotificationStatusModalProps
|
||||||
errors.status ? 'border-red-500' : 'border-gray-300'
|
errors.status ? 'border-red-500' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value={NotificationStatusEnum.Open}>Açık</option>
|
{Object.keys(NotificationStatusEnum).map((key) => (
|
||||||
<option value={NotificationStatusEnum.Assigned}>Atandı</option>
|
<option
|
||||||
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option>
|
key={key}
|
||||||
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option>
|
value={NotificationStatusEnum[key as keyof typeof NotificationStatusEnum]}
|
||||||
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
|
>
|
||||||
<option value={NotificationStatusEnum.Rejected}>Reddedildi</option>
|
{getNotificationStatusText(
|
||||||
|
NotificationStatusEnum[key as keyof typeof NotificationStatusEnum],
|
||||||
|
)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
{Object.values(NotificationStatusEnum).map((status) => (
|
||||||
|
<option key={status} value={status}>
|
||||||
|
{getNotificationStatusText(status)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.status && <p className="text-red-500 text-sm mt-1">{errors.status}</p>}
|
{errors.status && <p className="text-red-500 text-sm mt-1">{errors.status}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
|
||||||
import { PmFaultNotification, WorkOrderTypeEnum } from '../../../types/pm'
|
import { PmFaultNotification, WorkOrderTypeEnum } from '../../../types/pm'
|
||||||
import { MrpWorkOrder } from '../../../types/mrp'
|
import { MrpWorkOrder } from '../../../types/mrp'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getPriorityText, getWorkOrderTypeText } from '@/utils/erp'
|
||||||
|
|
||||||
interface CreateWorkOrderFromNotificationModalProps {
|
interface CreateWorkOrderFromNotificationModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -163,11 +164,11 @@ const CreateWorkOrderFromNotificationModal: React.FC<CreateWorkOrderFromNotifica
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici Bakım</option>
|
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici Bakım</option>
|
<option key={type} value={type}>
|
||||||
<option value={WorkOrderTypeEnum.Emergency}>Acil Müdahale</option>
|
{getWorkOrderTypeText(type)}
|
||||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
</option>
|
||||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -180,10 +181,11 @@ const CreateWorkOrderFromNotificationModal: React.FC<CreateWorkOrderFromNotifica
|
||||||
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
} from '../../../types/pm'
|
} from '../../../types/pm'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
import { getPriorityColor } from '../../../utils/erp'
|
import { getPriorityColor, getPriorityText } from '../../../utils/erp'
|
||||||
|
|
||||||
interface CreateWorkOrderModalProps {
|
interface CreateWorkOrderModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -243,10 +243,11 @@ const CreateWorkOrderModal: React.FC<CreateWorkOrderModalProps> = ({
|
||||||
onChange={(e) => handleCommonChange('priority', e.target.value as PriorityEnum)}
|
onChange={(e) => handleCommonChange('priority', e.target.value as PriorityEnum)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -329,10 +330,11 @@ const CreateWorkOrderModal: React.FC<CreateWorkOrderModalProps> = ({
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Ortak ayarı kullan</option>
|
<option value="">Ortak ayarı kullan</option>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,12 @@ import {
|
||||||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import {
|
||||||
|
getCriticalityLevelText,
|
||||||
|
getFaultTypeText,
|
||||||
|
getNotificationStatusText,
|
||||||
|
getPriorityText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
|
||||||
interface EditFaultNotificationModalProps {
|
interface EditFaultNotificationModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -260,12 +266,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={NotificationStatusEnum.Open}>Açık</option>
|
{Object.values(NotificationStatusEnum).map((status) => (
|
||||||
<option value={NotificationStatusEnum.Assigned}>Atandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option>
|
{getNotificationStatusText(status)}
|
||||||
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option>
|
</option>
|
||||||
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
|
))}
|
||||||
<option value={NotificationStatusEnum.Rejected}>Reddedildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -294,14 +299,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
|
||||||
onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)}
|
onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={FaultTypeEnum.Mechanical}>Mekanik</option>
|
{Object.values(FaultTypeEnum).map((faultType) => (
|
||||||
<option value={FaultTypeEnum.Electrical}>Elektrik</option>
|
<option key={faultType} value={faultType}>
|
||||||
<option value={FaultTypeEnum.Hydraulic}>Hidrolik</option>
|
{getFaultTypeText(faultType)}
|
||||||
<option value={FaultTypeEnum.Pneumatic}>Pnömatik</option>
|
</option>
|
||||||
<option value={FaultTypeEnum.Software}>Yazılım</option>
|
))}
|
||||||
<option value={FaultTypeEnum.Safety}>Güvenlik</option>
|
|
||||||
<option value={FaultTypeEnum.Performance}>Performans</option>
|
|
||||||
<option value={FaultTypeEnum.Other}>Diğer</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -312,10 +314,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
|
||||||
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -328,10 +331,11 @@ const EditFaultNotificationModal: React.FC<EditFaultNotificationModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
import { mockUnits } from '../../../mocks/mockUnits'
|
import { mockUnits } from '../../../mocks/mockUnits'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getFrequencyUnitText, getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
|
||||||
|
|
||||||
interface EditMaintenancePlanModalProps {
|
interface EditMaintenancePlanModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -154,10 +155,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option>
|
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||||
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option>
|
<option key={type} value={type}>
|
||||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option>
|
{getMaintenancePlanTypeText(type)}
|
||||||
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -168,10 +170,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
|
|
@ -214,12 +217,11 @@ const EditMaintenancePlanModal: React.FC<EditMaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={FrequencyUnitEnum.Days}>Gün</option>
|
{Object.values(FrequencyUnitEnum).map((unit) => (
|
||||||
<option value={FrequencyUnitEnum.Weeks}>Hafta</option>
|
<option key={unit} value={unit}>
|
||||||
<option value={FrequencyUnitEnum.Months}>Ay</option>
|
{getFrequencyUnitText(unit)}
|
||||||
<option value={FrequencyUnitEnum.Years}>Yıl</option>
|
</option>
|
||||||
<option value={FrequencyUnitEnum.Hours}>Saat</option>
|
))}
|
||||||
<option value={FrequencyUnitEnum.Cycles}>Çevrim</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { FaTimes, FaSave, FaPlus, FaMinus } from 'react-icons/fa'
|
||||||
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
import { Team, TeamMember, TeamRoleEnum } from '../../../types/common'
|
||||||
|
import { getTeamRoleText } from '@/utils/erp'
|
||||||
|
|
||||||
interface EditTeamModalProps {
|
interface EditTeamModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -252,9 +253,13 @@ const EditTeamModal: React.FC<EditTeamModalProps> = ({ isOpen, onClose, onSave,
|
||||||
}
|
}
|
||||||
className="text-xs px-2 py-1 border border-gray-300 rounded"
|
className="text-xs px-2 py-1 border border-gray-300 rounded"
|
||||||
>
|
>
|
||||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
{Object.values(TeamRoleEnum)
|
||||||
<option value={TeamRoleEnum.Lead}>Lider</option>
|
.filter((a) => a !== TeamRoleEnum.Manager)
|
||||||
<option value={TeamRoleEnum.Specialist}>Uzman</option>
|
.map((role) => (
|
||||||
|
<option key={role} value={role}>
|
||||||
|
{getTeamRoleText(role)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import {
|
||||||
PmWorkCenterSpecification,
|
PmWorkCenterSpecification,
|
||||||
} from '../../../types/pm'
|
} from '../../../types/pm'
|
||||||
import { mockDepartments } from '../../../mocks/mockDepartments'
|
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||||
|
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
|
||||||
|
import { mockWorkCenterMachineTypes } from '@/mocks/mockWorkCenterMachineTypes'
|
||||||
|
|
||||||
interface EditWorkCenterModalProps {
|
interface EditWorkCenterModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -138,14 +140,15 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">Makine Türü</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">Makine Türü</label>
|
||||||
<select
|
<select
|
||||||
name="machineType"
|
name="machineType"
|
||||||
value={formData.machineType || 'Manual'}
|
value={formData.machineType?.id}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="Manual">Manuel</option>
|
{mockWorkCenterMachineTypes.map((type) => (
|
||||||
<option value="CNC">CNC</option>
|
<option key={type.id} value={type.id}>
|
||||||
<option value="Automated">Otomatik</option>
|
{type.name}
|
||||||
<option value="Semi-Automated">Yarı Otomatik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -290,10 +293,11 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
{getWorkCenterStatusText(status)}
|
||||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -306,10 +310,11 @@ const EditWorkCenterModal: React.FC<EditWorkCenterModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getPriorityText, getWorkOrderStatusText, getWorkOrderTypeText } from '@/utils/erp'
|
||||||
|
|
||||||
interface EditWorkOrderModalProps {
|
interface EditWorkOrderModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -269,13 +270,11 @@ const EditWorkOrderModal: React.FC<EditWorkOrderModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||||
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkOrderStatusEnum.Released}>Serbest Bırakıldı</option>
|
{getWorkOrderStatusText(status)}
|
||||||
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
</option>
|
||||||
<option value={WorkOrderStatusEnum.OnHold}>Beklemede</option>
|
))}
|
||||||
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
|
|
||||||
<option value={WorkOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -312,11 +311,11 @@ const EditWorkOrderModal: React.FC<EditWorkOrderModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option>
|
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option>
|
<option key={type} value={type}>
|
||||||
<option value={WorkOrderTypeEnum.Emergency}>Acil</option>
|
{getWorkOrderTypeText(type)}
|
||||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
</option>
|
||||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -332,10 +331,11 @@ const EditWorkOrderModal: React.FC<EditWorkOrderModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -254,12 +254,11 @@ const FaultNotifications: React.FC = () => {
|
||||||
onChange={(e) => setStatusFilter(e.target.value as NotificationStatusEnum | 'all')}
|
onChange={(e) => setStatusFilter(e.target.value as NotificationStatusEnum | 'all')}
|
||||||
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
{Object.values(NotificationStatusEnum).map((status) => (
|
||||||
<option value={NotificationStatusEnum.Open}>Açık</option>
|
<option key={status} value={status}>
|
||||||
<option value={NotificationStatusEnum.Assigned}>Atandı</option>
|
{getNotificationStatusText(status)}
|
||||||
<option value={NotificationStatusEnum.InProgress}>Devam Ediyor</option>
|
</option>
|
||||||
<option value={NotificationStatusEnum.Resolved}>Çözüldü</option>
|
))}
|
||||||
<option value={NotificationStatusEnum.Closed}>Kapatıldı</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -269,10 +268,11 @@ const FaultNotifications: React.FC = () => {
|
||||||
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Öncelikler</option>
|
<option value="all">Tüm Öncelikler</option>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
getPriorityColor,
|
getPriorityColor,
|
||||||
getWorkOrderStatusColor,
|
getWorkOrderStatusColor,
|
||||||
getWorkOrderStatusIcon,
|
getWorkOrderStatusIcon,
|
||||||
|
getWorkOrderStatusText,
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
|
||||||
|
|
@ -312,10 +313,11 @@ const MaintenanceCalendar: React.FC = () => {
|
||||||
className="pl-9 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
className="pl-9 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value="scheduled">Planlanmış</option>
|
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
{getWorkOrderStatusText(status)}
|
||||||
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
PmMaintenancePlan,
|
PmMaintenancePlan,
|
||||||
} from '../../../types/pm'
|
} from '../../../types/pm'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
|
||||||
|
|
||||||
interface MaintenancePlanModalProps {
|
interface MaintenancePlanModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -123,10 +124,11 @@ const MaintenancePlanModal: React.FC<MaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option>
|
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||||
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option>
|
<option key={type} value={type}>
|
||||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option>
|
{getMaintenancePlanTypeText(type)}
|
||||||
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -137,10 +139,11 @@ const MaintenancePlanModal: React.FC<MaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import PlanStatusChangeModal from './PlanStatusChangeModal'
|
||||||
import Widget from '../../../components/common/Widget'
|
import Widget from '../../../components/common/Widget'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
import {
|
import {
|
||||||
getFrequencyUnitText,
|
getFrequencyUnitTextByFrequency,
|
||||||
getMaintenancePlanTypeColor,
|
getMaintenancePlanTypeColor,
|
||||||
getMaintenancePlanTypeText,
|
getMaintenancePlanTypeText,
|
||||||
getPriorityColor,
|
getPriorityColor,
|
||||||
|
|
@ -194,11 +194,11 @@ const MaintenancePlans: React.FC = () => {
|
||||||
onChange={(e) => setTypeFilter(e.target.value as MaintenancePlanTypeEnum | 'all')}
|
onChange={(e) => setTypeFilter(e.target.value as MaintenancePlanTypeEnum | 'all')}
|
||||||
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Tipler</option>
|
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici</option>
|
<option key={type} value={type}>
|
||||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici</option>
|
{getMaintenancePlanTypeText(type)}
|
||||||
<option value={MaintenancePlanTypeEnum.Predictive}>Tahminsel</option>
|
</option>
|
||||||
<option value={MaintenancePlanTypeEnum.Condition}>Duruma Bağlı</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -313,7 +313,7 @@ const MaintenancePlans: React.FC = () => {
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3 whitespace-nowrap">
|
<td className="px-4 py-3 whitespace-nowrap">
|
||||||
<div className="text-sm text-gray-900">
|
<div className="text-sm text-gray-900">
|
||||||
{getFrequencyUnitText(plan.frequency, plan.frequencyUnit)}
|
{getFrequencyUnitTextByFrequency(plan.frequency, plan.frequencyUnit)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-gray-500">{plan.estimatedDuration} dakika</div>
|
<div className="text-xs text-gray-500">{plan.estimatedDuration} dakika</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
|
|
@ -187,9 +187,11 @@ const MaintenanceTeams: React.FC = () => {
|
||||||
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Roller</option>
|
<option value="all">Tüm Roller</option>
|
||||||
<option value={TeamRoleEnum.Lead}>Lider</option>
|
{Object.values(TeamRoleEnum).map((role) => (
|
||||||
<option value={TeamRoleEnum.Specialist}>Uzman</option>
|
<option key={role} value={role}>
|
||||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
{getTeamRoleText(role)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
|
||||||
|
|
@ -274,10 +274,11 @@ const MaintenanceWorkOrders: React.FC = () => {
|
||||||
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||||
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
{getWorkOrderStatusText(status)}
|
||||||
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -287,11 +288,11 @@ const MaintenanceWorkOrders: React.FC = () => {
|
||||||
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Tipler</option>
|
<option value="all">Tüm Tipler</option>
|
||||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option>
|
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option>
|
<option key={type} value={type}>
|
||||||
<option value={WorkOrderTypeEnum.Emergency}>Acil</option>
|
{getWorkOrderTypeText(type)}
|
||||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
</option>
|
||||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { PmCalendarEvent, WorkOrderStatusEnum } from '../../../types/pm'
|
||||||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getPriorityText, getWorkOrderStatusText } from '@/utils/erp'
|
||||||
|
|
||||||
interface NewCalendarEventModalProps {
|
interface NewCalendarEventModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -220,10 +221,11 @@ const NewCalendarEventModal: React.FC<NewCalendarEventModalProps> = ({
|
||||||
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -331,14 +333,11 @@ const NewCalendarEventModal: React.FC<NewCalendarEventModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="scheduled">Planlanmış</option>
|
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkOrderStatusEnum.Planned}>Planlandı</option>
|
{getWorkOrderStatusText(status)}
|
||||||
<option value={WorkOrderStatusEnum.Released}>Serbest Bırakıldı</option>
|
</option>
|
||||||
<option value={WorkOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
))}
|
||||||
<option value={WorkOrderStatusEnum.OnHold}>Beklemede</option>
|
|
||||||
<option value={WorkOrderStatusEnum.Completed}>Tamamlandı</option>
|
|
||||||
<option value={WorkOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getCriticalityLevelText, getFaultTypeText, getPriorityText } from '@/utils/erp'
|
||||||
|
|
||||||
interface NewFaultNotificationModalProps {
|
interface NewFaultNotificationModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -274,14 +275,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
|
||||||
onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)}
|
onChange={(e) => handleInputChange('faultType', e.target.value as FaultTypeEnum)}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={FaultTypeEnum.Mechanical}>Mekanik</option>
|
{Object.values(FaultTypeEnum).map((faultType) => (
|
||||||
<option value={FaultTypeEnum.Electrical}>Elektrik</option>
|
<option key={faultType} value={faultType}>
|
||||||
<option value={FaultTypeEnum.Hydraulic}>Hidrolik</option>
|
{getFaultTypeText(faultType)}
|
||||||
<option value={FaultTypeEnum.Pneumatic}>Pnömatik</option>
|
</option>
|
||||||
<option value={FaultTypeEnum.Software}>Yazılım</option>
|
))}
|
||||||
<option value={FaultTypeEnum.Safety}>Güvenlik</option>
|
|
||||||
<option value={FaultTypeEnum.Performance}>Performans</option>
|
|
||||||
<option value={FaultTypeEnum.Other}>Diğer</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -292,10 +290,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
|
||||||
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
onChange={(e) => handleInputChange('priority', e.target.value as PriorityEnum)}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -308,10 +307,11 @@ const NewFaultNotificationModal: React.FC<NewFaultNotificationModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
import { mockUnits } from '../../../mocks/mockUnits'
|
import { mockUnits } from '../../../mocks/mockUnits'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getFrequencyUnitText, getMaintenancePlanTypeText, getPriorityText } from '@/utils/erp'
|
||||||
|
|
||||||
interface NewMaintenancePlanModalProps {
|
interface NewMaintenancePlanModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -158,10 +159,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={MaintenancePlanTypeEnum.Preventive}>Önleyici Bakım</option>
|
{Object.values(MaintenancePlanTypeEnum).map((type) => (
|
||||||
<option value={MaintenancePlanTypeEnum.Predictive}>Kestirimci Bakım</option>
|
<option key={type} value={type}>
|
||||||
<option value={MaintenancePlanTypeEnum.Corrective}>Düzeltici Bakım</option>
|
{getMaintenancePlanTypeText(type)}
|
||||||
<option value={MaintenancePlanTypeEnum.Condition}>Durum Bazlı Bakım</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -172,10 +174,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
|
|
@ -219,12 +222,11 @@ const NewMaintenancePlanModal: React.FC<NewMaintenancePlanModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={FrequencyUnitEnum.Days}>Gün</option>
|
{Object.values(FrequencyUnitEnum).map((unit) => (
|
||||||
<option value={FrequencyUnitEnum.Weeks}>Hafta</option>
|
<option key={unit} value={unit}>
|
||||||
<option value={FrequencyUnitEnum.Months}>Ay</option>
|
{getFrequencyUnitText(unit)}
|
||||||
<option value={FrequencyUnitEnum.Years}>Yıl</option>
|
</option>
|
||||||
<option value={FrequencyUnitEnum.Hours}>Saat</option>
|
))}
|
||||||
<option value={FrequencyUnitEnum.Cycles}>Çevrim</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { TeamRoleEnum } from '../../../types/common'
|
||||||
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { Team, TeamMember } from '../../../types/common'
|
import { Team, TeamMember } from '../../../types/common'
|
||||||
|
import { getTeamRoleText } from '@/utils/erp'
|
||||||
|
|
||||||
interface NewTeamModalProps {
|
interface NewTeamModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -259,10 +260,11 @@ const NewTeamModal: React.FC<NewTeamModalProps> = ({ isOpen, onClose, onSave })
|
||||||
}
|
}
|
||||||
className="text-xs px-1.5 py-1 border border-gray-300 rounded"
|
className="text-xs px-1.5 py-1 border border-gray-300 rounded"
|
||||||
>
|
>
|
||||||
<option value={TeamRoleEnum.Member}>Üye</option>
|
{Object.values(TeamRoleEnum).map((role) => (
|
||||||
<option value={TeamRoleEnum.Lead}>Lider</option>
|
<option key={role} value={role}>
|
||||||
<option value={TeamRoleEnum.Specialist}>Uzman</option>
|
{getTeamRoleText(role)}
|
||||||
<option value={TeamRoleEnum.Manager}>Yönetici</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {
|
||||||
CriticalityLevelEnum,
|
CriticalityLevelEnum,
|
||||||
PmWorkCenterSpecification,
|
PmWorkCenterSpecification,
|
||||||
} from '../../../types/pm'
|
} from '../../../types/pm'
|
||||||
|
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
|
||||||
|
|
||||||
interface NewWorkCenterModalProps {
|
interface NewWorkCenterModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -249,10 +250,11 @@ const NewWorkCenterModal: React.FC<NewWorkCenterModalProps> = ({ isOpen, onClose
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
{getWorkCenterStatusText(status)}
|
||||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -265,10 +267,11 @@ const NewWorkCenterModal: React.FC<NewWorkCenterModalProps> = ({ isOpen, onClose
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import { mockMaintenanceTeams } from '../../../mocks/mockMaintenanceTeams'
|
||||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { mockMaterials } from '../../../mocks/mockMaterials'
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getPriorityText, getWorkOrderTypeText } from '@/utils/erp'
|
||||||
|
|
||||||
interface NewWorkOrderModalProps {
|
interface NewWorkOrderModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -242,11 +243,11 @@ const NewWorkOrderModal: React.FC<NewWorkOrderModalProps> = ({ isOpen, onClose,
|
||||||
}
|
}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkOrderTypeEnum.Preventive}>Önleyici</option>
|
{Object.values(WorkOrderTypeEnum).map((type) => (
|
||||||
<option value={WorkOrderTypeEnum.Corrective}>Düzeltici</option>
|
<option key={type} value={type}>
|
||||||
<option value={WorkOrderTypeEnum.Emergency}>Acil</option>
|
{getWorkOrderTypeText(type)}
|
||||||
<option value={WorkOrderTypeEnum.Inspection}>İnceleme</option>
|
</option>
|
||||||
<option value={WorkOrderTypeEnum.Calibration}>Kalibrasyon</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -262,10 +263,11 @@ const NewWorkOrderModal: React.FC<NewWorkOrderModalProps> = ({ isOpen, onClose,
|
||||||
}
|
}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -102,10 +102,11 @@ const StatusUpdateModal: React.FC<StatusUpdateModalProps> = ({
|
||||||
onChange={(e) => setNewStatus(e.target.value as WorkCenterStatusEnum)}
|
onChange={(e) => setNewStatus(e.target.value as WorkCenterStatusEnum)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
{getWorkCenterStatusText(status)}
|
||||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
{isStatusCritical && (
|
{isStatusCritical && (
|
||||||
|
|
@ -145,10 +146,11 @@ const StatusUpdateModal: React.FC<StatusUpdateModalProps> = ({
|
||||||
onChange={(e) => setNewCriticality(e.target.value as CriticalityLevelEnum)}
|
onChange={(e) => setNewCriticality(e.target.value as CriticalityLevelEnum)}
|
||||||
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -238,10 +238,11 @@ const WorkCenterCards: React.FC = () => {
|
||||||
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
{getWorkCenterStatusText(status)}
|
||||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -250,11 +251,11 @@ const WorkCenterCards: React.FC = () => {
|
||||||
onChange={(e) => setCriticalityFilter(e.target.value as CriticalityLevelEnum | 'all')}
|
onChange={(e) => setCriticalityFilter(e.target.value as CriticalityLevelEnum | 'all')}
|
||||||
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-4 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Kritiklik</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
</option>
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||||
import { HrDepartment } from '../../../types/hr'
|
import { HrDepartment } from '../../../types/hr'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { getCriticalityLevelText, getWorkCenterStatusText } from '@/utils/erp'
|
||||||
|
|
||||||
interface ValidationErrors {
|
interface ValidationErrors {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
|
|
@ -65,7 +66,7 @@ const WorkCenterForm: React.FC = () => {
|
||||||
capacity: 0,
|
capacity: 0,
|
||||||
costPerHour: 0,
|
costPerHour: 0,
|
||||||
setupTime: 0,
|
setupTime: 0,
|
||||||
machineType: '',
|
machineTypeId: '',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date('2022-03-15'),
|
creationTime: new Date('2022-03-15'),
|
||||||
lastModificationTime: new Date('2024-01-15'),
|
lastModificationTime: new Date('2024-01-15'),
|
||||||
|
|
@ -288,12 +289,11 @@ const WorkCenterForm: React.FC = () => {
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value="">Tip seçin</option>
|
<option value="">Tip seçin</option>
|
||||||
<option value="MACHINE">Makine</option>
|
{mockWorkCenters.map((wc) => (
|
||||||
<option value="VEHICLE">Araç</option>
|
<option key={wc.workCenterType?.id} value={wc.workCenterType?.id}>
|
||||||
<option value="TOOL">Alet</option>
|
{wc.workCenterType?.code} - {wc.workCenterType?.name}
|
||||||
<option value="FACILITY">Tesis</option>
|
</option>
|
||||||
<option value="SYSTEM">Sistem</option>
|
))}
|
||||||
<option value="OTHER">Diğer</option>
|
|
||||||
</select>
|
</select>
|
||||||
{errors.workCenterType && (
|
{errors.workCenterType && (
|
||||||
<p className="mt-1 text-sm text-red-600">{errors.workCenterType}</p>
|
<p className="mt-1 text-sm text-red-600">{errors.workCenterType}</p>
|
||||||
|
|
@ -428,10 +428,11 @@ const WorkCenterForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('status', e.target.value)}
|
onChange={(e) => handleInputChange('status', e.target.value)}
|
||||||
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="OPERATIONAL">Çalışır Durumda</option>
|
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||||
<option value="DOWN">Arızalı</option>
|
<option key={status} value={status}>
|
||||||
<option value="MAINTENANCE">Bakımda</option>
|
{getWorkCenterStatusText(status)}
|
||||||
<option value="RETIRED">Kullanım Dışı</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -444,10 +445,11 @@ const WorkCenterForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('criticality', e.target.value)}
|
onChange={(e) => handleInputChange('criticality', e.target.value)}
|
||||||
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:border-blue-500 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="LOW">Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value="MEDIUM">Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value="HIGH">Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value="CRITICAL">Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,11 @@ const WorkCenterList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={WorkCenterStatusEnum.Operational}>Operasyonel</option>
|
{Object.values(WorkCenterStatusEnum).map((status) => (
|
||||||
<option value={WorkCenterStatusEnum.UnderMaintenance}>Bakımda</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkCenterStatusEnum.OutOfOrder}>Arızalı</option>
|
{getWorkCenterStatusText(status)}
|
||||||
<option value={WorkCenterStatusEnum.Retired}>Emekli</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -156,10 +157,11 @@ const WorkCenterList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={CriticalityLevelEnum.Low}>Düşük</option>
|
{Object.values(CriticalityLevelEnum).map((level) => (
|
||||||
<option value={CriticalityLevelEnum.Medium}>Orta</option>
|
<option key={level} value={level}>
|
||||||
<option value={CriticalityLevelEnum.High}>Yüksek</option>
|
{getCriticalityLevelText(level)}
|
||||||
<option value={CriticalityLevelEnum.Critical}>Kritik</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import { MrpBOM, MrpBOMComponent, MrpBOMOperation } from '../../../types/mrp'
|
import { MrpBOM, MrpBOMComponent, MrpBOMOperation } from '../../../types/mrp'
|
||||||
import BOMFormModal from './BOMFormModal'
|
import BOMFormModal from './BOMFormModal'
|
||||||
import { getBOMTypeColor, getBOMTypeName } from '../../../utils/erp'
|
import { getBOMTypeColor, getBOMTypeText } from '../../../utils/erp'
|
||||||
import { mockBOMs } from '../../../mocks/mockBOMs'
|
import { mockBOMs } from '../../../mocks/mockBOMs'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
|
||||||
|
|
@ -82,9 +82,7 @@ const BOMManagement: React.FC = () => {
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Ürün Ağaçları (BOM)</h2>
|
<h2 className="text-2xl font-bold text-gray-900">Ürün Ağaçları (BOM)</h2>
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600">Ürün bileşenlerini ve üretim operasyonlarını yönetin</p>
|
||||||
Ürün bileşenlerini ve üretim operasyonlarını yönetin
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={handleAddNew}
|
onClick={handleAddNew}
|
||||||
|
|
@ -126,7 +124,7 @@ const BOMManagement: React.FC = () => {
|
||||||
bom.bomType,
|
bom.bomType,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getBOMTypeName(bom.bomType)}
|
{getBOMTypeText(bom.bomType)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-gray-600 mb-0.5">
|
<p className="text-sm text-gray-600 mb-0.5">
|
||||||
|
|
@ -235,7 +233,7 @@ const BOMManagement: React.FC = () => {
|
||||||
Malzeme: {selectedBOM.material?.code} - {selectedBOM.material?.name}
|
Malzeme: {selectedBOM.material?.code} - {selectedBOM.material?.name}
|
||||||
</div>
|
</div>
|
||||||
<div>Versiyon: {selectedBOM.version}</div>
|
<div>Versiyon: {selectedBOM.version}</div>
|
||||||
<div>Tip: {getBOMTypeName(selectedBOM.bomType)}</div>
|
<div>Tip: {getBOMTypeText(selectedBOM.bomType)}</div>
|
||||||
<div>Temel Miktar: {selectedBOM.baseQuantity}</div>
|
<div>Temel Miktar: {selectedBOM.baseQuantity}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaTimes, FaSave } from "react-icons/fa";
|
import { FaTimes, FaSave } from 'react-icons/fa'
|
||||||
import { MrpDemandForecast, ForecastMethodEnum } from "../../../types/mrp";
|
import { MrpDemandForecast, ForecastMethodEnum } from '../../../types/mrp'
|
||||||
import { mockMaterials } from "../../../mocks/mockMaterials";
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
|
import { getForecastMethodText } from '@/utils/erp'
|
||||||
|
|
||||||
interface DemandForecastFormModalProps {
|
interface DemandForecastFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (
|
onSave: (forecastData: Omit<MrpDemandForecast, 'id' | 'material'> & { id?: string }) => void
|
||||||
forecastData: Omit<MrpDemandForecast, "id" | "material"> & { id?: string }
|
initialData: MrpDemandForecast | null
|
||||||
) => void;
|
|
||||||
initialData: MrpDemandForecast | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
|
|
@ -19,9 +18,9 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
initialData,
|
initialData,
|
||||||
}) => {
|
}) => {
|
||||||
const newFormData: MrpDemandForecast = {
|
const newFormData: MrpDemandForecast = {
|
||||||
id: "",
|
id: '',
|
||||||
materialId: "",
|
materialId: '',
|
||||||
forecastPeriod: "",
|
forecastPeriod: '',
|
||||||
startDate: new Date(),
|
startDate: new Date(),
|
||||||
endDate: new Date(),
|
endDate: new Date(),
|
||||||
forecastMethod: ForecastMethodEnum.MovingAverage,
|
forecastMethod: ForecastMethodEnum.MovingAverage,
|
||||||
|
|
@ -32,10 +31,10 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
trendFactor: 0,
|
trendFactor: 0,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
notes: "",
|
notes: '',
|
||||||
};
|
}
|
||||||
|
|
||||||
const [formData, setFormData] = useState(newFormData);
|
const [formData, setFormData] = useState(newFormData)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialData) {
|
if (initialData) {
|
||||||
|
|
@ -43,36 +42,33 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
...initialData,
|
...initialData,
|
||||||
startDate: new Date(initialData.startDate),
|
startDate: new Date(initialData.startDate),
|
||||||
endDate: new Date(initialData.endDate),
|
endDate: new Date(initialData.endDate),
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData(newFormData);
|
setFormData(newFormData)
|
||||||
}
|
}
|
||||||
}, [initialData, isOpen]);
|
}, [initialData, isOpen])
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
const saveData = {
|
const saveData = {
|
||||||
...formData,
|
...formData,
|
||||||
id: initialData?.id,
|
id: initialData?.id,
|
||||||
startDate: new Date(formData.startDate),
|
startDate: new Date(formData.startDate),
|
||||||
endDate: new Date(formData.endDate),
|
endDate: new Date(formData.endDate),
|
||||||
};
|
}
|
||||||
onSave(saveData);
|
onSave(saveData)
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-4 border-b">
|
<div className="flex items-center justify-between p-4 border-b">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{initialData ? "Talep Tahmini Düzenle" : "Yeni Talep Tahmini"}
|
{initialData ? 'Talep Tahmini Düzenle' : 'Yeni Talep Tahmini'}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-4 h-4" />
|
<FaTimes className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -80,15 +76,11 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
<form onSubmit={handleSubmit} className="p-4 space-y-4">
|
<form onSubmit={handleSubmit} className="p-4 space-y-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Malzeme</label>
|
||||||
Malzeme
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.materialId}
|
value={formData.materialId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, materialId: e.target.value })}
|
||||||
setFormData({ ...formData, materialId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Seçiniz</option>
|
<option value="">Seçiniz</option>
|
||||||
|
|
@ -108,9 +100,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
value={formData.forecastPeriod}
|
value={formData.forecastPeriod}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, forecastPeriod: e.target.value })}
|
||||||
setFormData({ ...formData, forecastPeriod: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="Örn: 2024-Q3"
|
placeholder="Örn: 2024-Q3"
|
||||||
/>
|
/>
|
||||||
|
|
@ -123,7 +113,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={formData.startDate.toISOString().split("T")[0]}
|
value={formData.startDate.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -135,13 +125,11 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Bitiş Tarihi</label>
|
||||||
Bitiş Tarihi
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={formData.endDate.toISOString().split("T")[0]}
|
value={formData.endDate.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -153,9 +141,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Tahmin Yöntemi</label>
|
||||||
Tahmin Yöntemi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.forecastMethod}
|
value={formData.forecastMethod}
|
||||||
|
|
@ -167,23 +153,16 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={ForecastMethodEnum.MovingAverage}>
|
{Object.values(ForecastMethodEnum).map((method) => (
|
||||||
Hareketli Ortalama
|
<option key={method} value={method}>
|
||||||
</option>
|
{getForecastMethodText(method)}
|
||||||
<option value={ForecastMethodEnum.ExponentialSmoothing}>
|
</option>
|
||||||
Üstel Yumuşatma
|
))}
|
||||||
</option>
|
|
||||||
<option value={ForecastMethodEnum.LinearRegression}>
|
|
||||||
Doğrusal Regresyon
|
|
||||||
</option>
|
|
||||||
<option value={ForecastMethodEnum.Seasonal}>Mevsimsel</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Tahmin Miktarı</label>
|
||||||
Tahmin Miktarı
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
required
|
required
|
||||||
|
|
@ -219,7 +198,7 @@ const DemandForecastFormModal: React.FC<DemandForecastFormModalProps> = ({
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default DemandForecastFormModal;
|
export default DemandForecastFormModal
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaTimes, FaSave } from "react-icons/fa";
|
import { FaTimes, FaSave } from 'react-icons/fa'
|
||||||
import { MrpWorkOrder } from "../../../types/mrp";
|
import { MrpWorkOrder } from '../../../types/mrp'
|
||||||
import { mockProductionOrders } from "../../../mocks/mockProductionOrders";
|
import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
|
||||||
import { mockOperations } from "../../../mocks/mockOperations";
|
import { mockOperations } from '../../../mocks/mockOperations'
|
||||||
import { mockMaterials } from "../../../mocks/mockMaterials";
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
import { mockWorkCenters } from "../../../mocks/mockWorkCenters";
|
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { WorkOrderStatusEnum } from "../../../types/pm";
|
import { WorkOrderStatusEnum } from '../../../types/pm'
|
||||||
|
import { getWorkOrderStatusText } from '@/utils/erp'
|
||||||
|
|
||||||
interface EditWorkOrderFormProps {
|
interface EditWorkOrderFormProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (workOrder: MrpWorkOrder) => void;
|
onSave: (workOrder: MrpWorkOrder) => void
|
||||||
workOrder: MrpWorkOrder | null;
|
workOrder: MrpWorkOrder | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
|
|
@ -21,20 +22,20 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
workOrder,
|
workOrder,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
workOrderNumber: "",
|
workOrderNumber: '',
|
||||||
productionOrderId: "",
|
productionOrderId: '',
|
||||||
operationId: "",
|
operationId: '',
|
||||||
materialId: "",
|
materialId: '',
|
||||||
sequence: 1,
|
sequence: 1,
|
||||||
plannedStartDate: "",
|
plannedStartDate: '',
|
||||||
plannedEndDate: "",
|
plannedEndDate: '',
|
||||||
plannedQuantity: 0,
|
plannedQuantity: 0,
|
||||||
workCenterId: "",
|
workCenterId: '',
|
||||||
assignedOperators: [] as string[],
|
assignedOperators: [] as string[],
|
||||||
setupTime: 0,
|
setupTime: 0,
|
||||||
processTime: 0,
|
processTime: 0,
|
||||||
status: WorkOrderStatusEnum.Created,
|
status: WorkOrderStatusEnum.Created,
|
||||||
});
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workOrder) {
|
if (workOrder) {
|
||||||
|
|
@ -44,23 +45,21 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
operationId: workOrder.operationId,
|
operationId: workOrder.operationId,
|
||||||
materialId: workOrder.materialId,
|
materialId: workOrder.materialId,
|
||||||
sequence: workOrder.sequence,
|
sequence: workOrder.sequence,
|
||||||
plannedStartDate: workOrder.plannedStartDate
|
plannedStartDate: workOrder.plannedStartDate.toISOString().split('T')[0],
|
||||||
.toISOString()
|
plannedEndDate: workOrder.plannedEndDate.toISOString().split('T')[0],
|
||||||
.split("T")[0],
|
|
||||||
plannedEndDate: workOrder.plannedEndDate.toISOString().split("T")[0],
|
|
||||||
plannedQuantity: workOrder.plannedQuantity,
|
plannedQuantity: workOrder.plannedQuantity,
|
||||||
workCenterId: workOrder.workCenterId,
|
workCenterId: workOrder.workCenterId,
|
||||||
assignedOperators: workOrder.assignedOperators,
|
assignedOperators: workOrder.assignedOperators,
|
||||||
setupTime: workOrder.setupTime,
|
setupTime: workOrder.setupTime,
|
||||||
processTime: workOrder.processTime,
|
processTime: workOrder.processTime,
|
||||||
status: workOrder.status,
|
status: workOrder.status,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}, [workOrder]);
|
}, [workOrder])
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (!workOrder) return;
|
if (!workOrder) return
|
||||||
|
|
||||||
const updatedWorkOrder: MrpWorkOrder = {
|
const updatedWorkOrder: MrpWorkOrder = {
|
||||||
...workOrder,
|
...workOrder,
|
||||||
|
|
@ -68,24 +67,19 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
plannedStartDate: new Date(formData.plannedStartDate),
|
plannedStartDate: new Date(formData.plannedStartDate),
|
||||||
plannedEndDate: new Date(formData.plannedEndDate),
|
plannedEndDate: new Date(formData.plannedEndDate),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
};
|
}
|
||||||
onSave(updatedWorkOrder);
|
onSave(updatedWorkOrder)
|
||||||
onClose();
|
onClose()
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen || !workOrder) return null;
|
if (!isOpen || !workOrder) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-4 border-b">
|
<div className="flex items-center justify-between p-4 border-b">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">İş Emri Düzenle</h2>
|
||||||
İş Emri Düzenle
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-4 h-4" />
|
<FaTimes className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -100,18 +94,14 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
value={formData.workOrderNumber}
|
value={formData.workOrderNumber}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, workOrderNumber: e.target.value })}
|
||||||
setFormData({ ...formData, workOrderNumber: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
placeholder="WO-2024-XXX"
|
placeholder="WO-2024-XXX"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Üretim Emri</label>
|
||||||
Üretim Emri
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.productionOrderId}
|
value={formData.productionOrderId}
|
||||||
|
|
@ -133,15 +123,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Operasyon</label>
|
||||||
Operasyon
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.operationId}
|
value={formData.operationId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, operationId: e.target.value })}
|
||||||
setFormData({ ...formData, operationId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Seçiniz</option>
|
<option value="">Seçiniz</option>
|
||||||
|
|
@ -154,15 +140,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Malzeme</label>
|
||||||
Malzeme
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.materialId}
|
value={formData.materialId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, materialId: e.target.value })}
|
||||||
setFormData({ ...formData, materialId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Seçiniz</option>
|
<option value="">Seçiniz</option>
|
||||||
|
|
@ -175,15 +157,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">İş Merkezi</label>
|
||||||
İş Merkezi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.workCenterId}
|
value={formData.workCenterId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, workCenterId: e.target.value })}
|
||||||
setFormData({ ...formData, workCenterId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Seçiniz</option>
|
<option value="">Seçiniz</option>
|
||||||
|
|
@ -196,9 +174,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Sıra</label>
|
||||||
Sıra
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
required
|
required
|
||||||
|
|
@ -222,9 +198,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={formData.plannedStartDate}
|
value={formData.plannedStartDate}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, plannedStartDate: e.target.value })}
|
||||||
setFormData({ ...formData, plannedStartDate: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -237,9 +211,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={formData.plannedEndDate}
|
value={formData.plannedEndDate}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, plannedEndDate: e.target.value })}
|
||||||
setFormData({ ...formData, plannedEndDate: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -302,9 +274,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||||
Durum
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.status}
|
value={formData.status}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
|
@ -315,15 +285,11 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
}
|
}
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={WorkOrderStatusEnum.Created}>Oluşturuldu</option>
|
{Object.values(WorkOrderStatusEnum).map((status) => (
|
||||||
<option value={WorkOrderStatusEnum.Released}>Yayınlandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={WorkOrderStatusEnum.InProgress}>İşlemde</option>
|
{getWorkOrderStatusText(status)}
|
||||||
<option value={WorkOrderStatusEnum.Completed}>
|
</option>
|
||||||
Tamamlandı
|
))}
|
||||||
</option>
|
|
||||||
<option value={WorkOrderStatusEnum.Cancelled}>
|
|
||||||
İptal Edildi
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -347,7 +313,7 @@ const EditWorkOrderForm: React.FC<EditWorkOrderFormProps> = ({
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default EditWorkOrderForm;
|
export default EditWorkOrderForm
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,24 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaTimes, FaSave } from "react-icons/fa";
|
import { FaTimes, FaSave } from 'react-icons/fa'
|
||||||
import {
|
import { MrpMaterialRequirement, RequirementSourceTypeEnum } from '../../../types/mrp'
|
||||||
MrpMaterialRequirement,
|
import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
RequirementSourceTypeEnum,
|
import { getRequirementSourceTypeText } from '@/utils/erp'
|
||||||
} from "../../../types/mrp";
|
|
||||||
import { mockMaterials } from "../../../mocks/mockMaterials";
|
|
||||||
|
|
||||||
interface MaterialRequirementFormModalProps {
|
interface MaterialRequirementFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (
|
onSave: (reqData: Omit<MrpMaterialRequirement, 'id' | 'material'> & { id?: string }) => void
|
||||||
reqData: Omit<MrpMaterialRequirement, "id" | "material"> & { id?: string }
|
initialData: MrpMaterialRequirement | null
|
||||||
) => void;
|
|
||||||
initialData: MrpMaterialRequirement | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MaterialRequirementFormModal: React.FC<
|
const MaterialRequirementFormModal: React.FC<MaterialRequirementFormModalProps> = ({
|
||||||
MaterialRequirementFormModalProps
|
isOpen,
|
||||||
> = ({ isOpen, onClose, onSave, initialData }) => {
|
onClose,
|
||||||
|
onSave,
|
||||||
|
initialData,
|
||||||
|
}) => {
|
||||||
const newFormData: MrpMaterialRequirement = {
|
const newFormData: MrpMaterialRequirement = {
|
||||||
materialId: "",
|
materialId: '',
|
||||||
sourceType: RequirementSourceTypeEnum.Forecast,
|
sourceType: RequirementSourceTypeEnum.Forecast,
|
||||||
grossRequirement: 0,
|
grossRequirement: 0,
|
||||||
netRequirement: 0,
|
netRequirement: 0,
|
||||||
|
|
@ -29,14 +28,14 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
plannedOrderRelease: 0,
|
plannedOrderRelease: 0,
|
||||||
requirementDate: new Date(),
|
requirementDate: new Date(),
|
||||||
plannedReceiptDate: new Date(),
|
plannedReceiptDate: new Date(),
|
||||||
id: "",
|
id: '',
|
||||||
mrpRunId: "",
|
mrpRunId: '',
|
||||||
plannedReleaseDate: new Date(),
|
plannedReleaseDate: new Date(),
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
};
|
}
|
||||||
|
|
||||||
const [formData, setFormData] = useState(newFormData);
|
const [formData, setFormData] = useState(newFormData)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialData) {
|
if (initialData) {
|
||||||
|
|
@ -44,37 +43,34 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
...initialData,
|
...initialData,
|
||||||
requirementDate: new Date(initialData.requirementDate),
|
requirementDate: new Date(initialData.requirementDate),
|
||||||
plannedReceiptDate: new Date(initialData.plannedReceiptDate),
|
plannedReceiptDate: new Date(initialData.plannedReceiptDate),
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
// Reset form for new entry
|
// Reset form for new entry
|
||||||
setFormData(newFormData);
|
setFormData(newFormData)
|
||||||
}
|
}
|
||||||
}, [initialData, isOpen]);
|
}, [initialData, isOpen])
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
const saveData = {
|
const saveData = {
|
||||||
...formData,
|
...formData,
|
||||||
id: initialData?.id,
|
id: initialData?.id,
|
||||||
requirementDate: new Date(formData.requirementDate),
|
requirementDate: new Date(formData.requirementDate),
|
||||||
plannedReceiptDate: new Date(formData.plannedReceiptDate),
|
plannedReceiptDate: new Date(formData.plannedReceiptDate),
|
||||||
};
|
}
|
||||||
onSave(saveData);
|
onSave(saveData)
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-4 border-b">
|
<div className="flex items-center justify-between p-4 border-b">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{initialData ? "Malzeme İhtiyacı Düzenle" : "Yeni Malzeme İhtiyacı"}
|
{initialData ? 'Malzeme İhtiyacı Düzenle' : 'Yeni Malzeme İhtiyacı'}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-4 h-4" />
|
<FaTimes className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -82,15 +78,11 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
<form onSubmit={handleSubmit} className="p-4 space-y-4">
|
<form onSubmit={handleSubmit} className="p-4 space-y-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Malzeme</label>
|
||||||
Malzeme
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.materialId}
|
value={formData.materialId}
|
||||||
onChange={(e) =>
|
onChange={(e) => setFormData({ ...formData, materialId: e.target.value })}
|
||||||
setFormData({ ...formData, materialId: e.target.value })
|
|
||||||
}
|
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Seçiniz</option>
|
<option value="">Seçiniz</option>
|
||||||
|
|
@ -103,9 +95,7 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Kaynak Tipi</label>
|
||||||
Kaynak Tipi
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
required
|
required
|
||||||
value={formData.sourceType}
|
value={formData.sourceType}
|
||||||
|
|
@ -117,25 +107,16 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
}
|
}
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={RequirementSourceTypeEnum.Forecast}>
|
{Object.values(RequirementSourceTypeEnum).map((type) => (
|
||||||
Tahmin
|
<option key={type} value={type}>
|
||||||
</option>
|
{getRequirementSourceTypeText(type)}
|
||||||
<option value={RequirementSourceTypeEnum.SalesOrder}>
|
</option>
|
||||||
Satış Siparişi
|
))}
|
||||||
</option>
|
|
||||||
<option value={RequirementSourceTypeEnum.SafetyStock}>
|
|
||||||
Güvenlik Stoku
|
|
||||||
</option>
|
|
||||||
<option value={RequirementSourceTypeEnum.ProductionOrder}>
|
|
||||||
Üretim Emri
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Brüt İhtiyaç</label>
|
||||||
Brüt İhtiyaç
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
required
|
required
|
||||||
|
|
@ -152,9 +133,7 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Net İhtiyaç</label>
|
||||||
Net İhtiyaç
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
required
|
required
|
||||||
|
|
@ -170,13 +149,11 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">İhtiyaç Tarihi</label>
|
||||||
İhtiyaç Tarihi
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={formData.requirementDate.toISOString().split("T")[0]}
|
value={formData.requirementDate.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -194,7 +171,7 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={formData.plannedReceiptDate.toISOString().split("T")[0]}
|
value={formData.plannedReceiptDate.toISOString().split('T')[0]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
|
|
@ -225,7 +202,7 @@ const MaterialRequirementFormModal: React.FC<
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default MaterialRequirementFormModal;
|
export default MaterialRequirementFormModal
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { FaSave, FaTimes } from "react-icons/fa";
|
import { FaSave, FaTimes } from 'react-icons/fa'
|
||||||
import {
|
import { OperationCategoryEnum, MrpOperationTypeDefinition } from '../../../types/mrp'
|
||||||
OperationCategoryEnum,
|
import { getOperationTypeText } from '@/utils/erp'
|
||||||
MrpOperationTypeDefinition,
|
|
||||||
} from "../../../types/mrp";
|
|
||||||
|
|
||||||
interface OperationTypeFormProps {
|
interface OperationTypeFormProps {
|
||||||
open: boolean;
|
open: boolean
|
||||||
initial?: MrpOperationTypeDefinition | null;
|
initial?: MrpOperationTypeDefinition | null
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSave: (data: MrpOperationTypeDefinition) => void;
|
onSave: (data: MrpOperationTypeDefinition) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
|
|
@ -18,13 +16,13 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
onClose,
|
onClose,
|
||||||
onSave,
|
onSave,
|
||||||
}) => {
|
}) => {
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false)
|
||||||
const [form, setForm] = useState<MrpOperationTypeDefinition>(
|
const [form, setForm] = useState<MrpOperationTypeDefinition>(
|
||||||
initial || {
|
initial || {
|
||||||
id: "",
|
id: '',
|
||||||
code: "",
|
code: '',
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
category: OperationCategoryEnum.Setup,
|
category: OperationCategoryEnum.Setup,
|
||||||
defaultDuration: 0,
|
defaultDuration: 0,
|
||||||
requiresSetup: false,
|
requiresSetup: false,
|
||||||
|
|
@ -34,85 +32,79 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
isActive: true,
|
isActive: true,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
}
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initial) setForm(initial);
|
if (initial) setForm(initial)
|
||||||
else
|
else
|
||||||
setForm((prev) => ({
|
setForm((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
id: "",
|
id: '',
|
||||||
code: "",
|
code: '',
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
}));
|
}))
|
||||||
}, [initial, open]);
|
}, [initial, open])
|
||||||
|
|
||||||
if (!open) return null;
|
if (!open) return null
|
||||||
|
|
||||||
const handleChange = (
|
const handleChange = (
|
||||||
field: keyof MrpOperationTypeDefinition,
|
field: keyof MrpOperationTypeDefinition,
|
||||||
value: string | number | boolean
|
value: string | number | boolean,
|
||||||
) => {
|
) => {
|
||||||
setForm((s) => ({
|
setForm((s) => ({
|
||||||
...s,
|
...s,
|
||||||
[field]: value,
|
[field]: value,
|
||||||
lastModificationTime: new Date(),
|
lastModificationTime: new Date(),
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
setSaving(true);
|
setSaving(true)
|
||||||
try {
|
try {
|
||||||
// simulate API
|
// simulate API
|
||||||
await new Promise((r) => setTimeout(r, 600));
|
await new Promise((r) => setTimeout(r, 600))
|
||||||
onSave({ ...form, id: form.id || String(Date.now()) });
|
onSave({ ...form, id: form.id || String(Date.now()) })
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white rounded-lg p-4 w-full max-w-xl mx-4">
|
<div className="bg-white rounded-lg p-4 w-full max-w-xl mx-4">
|
||||||
<h3 className="text-lg font-semibold mb-3">
|
<h3 className="text-lg font-semibold mb-3">
|
||||||
{form.id ? "Operasyon Türünü Düzenle" : "Yeni Operasyon Türü"}
|
{form.id ? 'Operasyon Türünü Düzenle' : 'Yeni Operasyon Türü'}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Kod</label>
|
||||||
Kod
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
autoFocus
|
autoFocus
|
||||||
value={form.code}
|
value={form.code}
|
||||||
onChange={(e) => handleChange("code", e.target.value)}
|
onChange={(e) => handleChange('code', e.target.value)}
|
||||||
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
||||||
placeholder="Örn: CUT001"
|
placeholder="Örn: CUT001"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Ad</label>
|
||||||
Ad
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
value={form.name}
|
value={form.name}
|
||||||
onChange={(e) => handleChange("name", e.target.value)}
|
onChange={(e) => handleChange('name', e.target.value)}
|
||||||
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
||||||
placeholder="Kesme İşlemi"
|
placeholder="Kesme İşlemi"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama</label>
|
||||||
Açıklama
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={form.description}
|
value={form.description}
|
||||||
onChange={(e) => handleChange("description", e.target.value)}
|
onChange={(e) => handleChange('description', e.target.value)}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
||||||
/>
|
/>
|
||||||
|
|
@ -120,27 +112,18 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Kategori</label>
|
||||||
Kategori
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={form.category}
|
value={form.category}
|
||||||
onChange={(e) => handleChange("category", e.target.value)}
|
onChange={(e) => handleChange('category', e.target.value)}
|
||||||
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
||||||
>
|
>
|
||||||
<option value="">Kategori seçin</option>
|
<option value="">Kategori seçin</option>
|
||||||
<option value={OperationCategoryEnum.Production}>Üretim</option>
|
{Object.values(OperationCategoryEnum).map((cat) => (
|
||||||
<option value={OperationCategoryEnum.Assembly}>Montaj</option>
|
<option key={cat} value={cat}>
|
||||||
<option value={OperationCategoryEnum.Inspection}>
|
{getOperationTypeText(cat)}
|
||||||
Kontrol
|
</option>
|
||||||
</option>
|
))}
|
||||||
<option value={OperationCategoryEnum.Packaging}>
|
|
||||||
Paketleme
|
|
||||||
</option>
|
|
||||||
<option value={OperationCategoryEnum.Setup}>Hazırlık</option>
|
|
||||||
<option value={OperationCategoryEnum.Maintenance}>Bakım</option>
|
|
||||||
<option value={OperationCategoryEnum.Transport}>Taşıma</option>
|
|
||||||
<option value={OperationCategoryEnum.Quality}>Kalite</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -150,9 +133,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={form.defaultDuration}
|
value={form.defaultDuration}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleChange('defaultDuration', Number(e.target.value))}
|
||||||
handleChange("defaultDuration", Number(e.target.value))
|
|
||||||
}
|
|
||||||
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
className="w-full border rounded-lg px-2 py-1.5 text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -163,9 +144,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={form.requiresSetup}
|
checked={form.requiresSetup}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleChange('requiresSetup', e.target.checked)}
|
||||||
handleChange("requiresSetup", e.target.checked)
|
|
||||||
}
|
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-gray-700">Hazırlık Gerekli</span>
|
<span className="text-sm text-gray-700">Hazırlık Gerekli</span>
|
||||||
|
|
@ -175,9 +154,7 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={form.allowsParallelOperation}
|
checked={form.allowsParallelOperation}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleChange('allowsParallelOperation', e.target.checked)}
|
||||||
handleChange("allowsParallelOperation", e.target.checked)
|
|
||||||
}
|
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-gray-700">Paralel İşlem</span>
|
<span className="text-sm text-gray-700">Paralel İşlem</span>
|
||||||
|
|
@ -197,13 +174,12 @@ const OperationTypeFormModal: React.FC<OperationTypeFormProps> = ({
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-400"
|
className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-400"
|
||||||
>
|
>
|
||||||
<FaSave className="inline mr-2" />{" "}
|
<FaSave className="inline mr-2" /> {saving ? 'Kaydediliyor...' : 'Kaydet'}
|
||||||
{saving ? "Kaydediliyor..." : "Kaydet"}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default OperationTypeFormModal;
|
export default OperationTypeFormModal
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,7 @@ import {
|
||||||
import { MrpOperationTypeDefinition } from '../../../types/mrp'
|
import { MrpOperationTypeDefinition } from '../../../types/mrp'
|
||||||
import OperationTypeFormModal from './OperationTypeFormModal'
|
import OperationTypeFormModal from './OperationTypeFormModal'
|
||||||
import { mockOperationTypes } from '../../../mocks/mockOperationTypes'
|
import { mockOperationTypes } from '../../../mocks/mockOperationTypes'
|
||||||
import {
|
import { getOperationTypeColor, getOperationTypeText, getSkillLevelText } from '../../../utils/erp'
|
||||||
getOperationCategoryColor,
|
|
||||||
getOperationTypeColor,
|
|
||||||
getOperationTypeText,
|
|
||||||
getSkillLevelText,
|
|
||||||
} from '../../../utils/erp'
|
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
|
||||||
const OperationTypes: React.FC = () => {
|
const OperationTypes: React.FC = () => {
|
||||||
|
|
@ -261,7 +256,7 @@ const OperationTypes: React.FC = () => {
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-2 whitespace-nowrap">
|
<td className="px-3 py-2 whitespace-nowrap">
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 rounded-full text-xs font-medium ${getOperationCategoryColor(
|
className={`px-2 py-1 rounded-full text-xs font-medium ${getOperationTypeText(
|
||||||
type.category,
|
type.category,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
|
import { mockProductionOrders } from '../../../mocks/mockProductionOrders'
|
||||||
import { mockWorkOrders } from '../../../mocks/mockWorkOrders'
|
import { mockWorkOrders } from '../../../mocks/mockWorkOrders'
|
||||||
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
import { mockWorkCenters } from '../../../mocks/mockWorkCenters'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { getFrequencyUnitText, getPriorityColor } from '../../../utils/erp'
|
||||||
import { getPriorityColor, getProductionOrderStatus, getWorkOrderStatus } from '../../../utils/erp'
|
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
import { FrequencyUnitEnum } from '@/types/pm'
|
||||||
|
|
||||||
interface PlanningGanttProps {
|
interface PlanningGanttProps {
|
||||||
workCenterId?: string
|
workCenterId?: string
|
||||||
|
|
@ -107,7 +107,7 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
|
||||||
assignee: wo.assignedOperators[0]
|
assignee: wo.assignedOperators[0]
|
||||||
? mockEmployees.find((e) => e.id === wo.assignedOperators[0])
|
? mockEmployees.find((e) => e.id === wo.assignedOperators[0])
|
||||||
: undefined,
|
: undefined,
|
||||||
status: getWorkOrderStatus(wo.status),
|
status: wo.status,
|
||||||
priority: order.priority,
|
priority: order.priority,
|
||||||
level: 1,
|
level: 1,
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -125,7 +125,7 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
|
||||||
order.confirmedQuantity && order.plannedQuantity
|
order.confirmedQuantity && order.plannedQuantity
|
||||||
? Math.round((order.confirmedQuantity / order.plannedQuantity) * 100)
|
? Math.round((order.confirmedQuantity / order.plannedQuantity) * 100)
|
||||||
: 0,
|
: 0,
|
||||||
status: getProductionOrderStatus(order.status),
|
status: order.status,
|
||||||
priority: order.priority,
|
priority: order.priority,
|
||||||
level: 0,
|
level: 0,
|
||||||
children: workOrders,
|
children: workOrders,
|
||||||
|
|
@ -480,10 +480,18 @@ const PlanningGantt: React.FC<PlanningGanttProps> = ({ workCenterId }) => {
|
||||||
onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')}
|
onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')}
|
||||||
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto"
|
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto"
|
||||||
>
|
>
|
||||||
<option value="day">Günlük</option>
|
<option value={FrequencyUnitEnum.Days}>
|
||||||
<option value="week">Haftalık</option>
|
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||||
<option value="month">Aylık</option>
|
</option>
|
||||||
<option value="year">Yıllık</option>
|
<option value={FrequencyUnitEnum.Weeks}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||||
|
</option>
|
||||||
|
<option value={FrequencyUnitEnum.Months}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||||
|
</option>
|
||||||
|
<option value={FrequencyUnitEnum.Years}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@ import { mockMaterials } from '../../../mocks/mockMaterials'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import {
|
||||||
|
getPriorityText,
|
||||||
|
getProductionOrderStatusText,
|
||||||
|
getProductionOrderTypeText,
|
||||||
|
} from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
const ProductionOrderForm: React.FC = () => {
|
const ProductionOrderForm: React.FC = () => {
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
|
|
@ -260,10 +266,11 @@ const ProductionOrderForm: React.FC = () => {
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
||||||
>
|
>
|
||||||
<option value={ProductionOrderTypeEnum.Standard}>Standart</option>
|
{Object.values(ProductionOrderTypeEnum).map((type) => (
|
||||||
<option value={ProductionOrderTypeEnum.Rework}>Yeniden İşleme</option>
|
<option key={type} value={type}>
|
||||||
<option value={ProductionOrderTypeEnum.Maintenance}>Bakım</option>
|
{getProductionOrderTypeText(type)}
|
||||||
<option value={ProductionOrderTypeEnum.Sample}>Numune</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -275,12 +282,11 @@ const ProductionOrderForm: React.FC = () => {
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
||||||
>
|
>
|
||||||
<option value={ProductionOrderStatusEnum.Created}>Oluşturuldu</option>
|
{Object.values(ProductionOrderStatusEnum).map((status) => (
|
||||||
<option value={ProductionOrderStatusEnum.Released}>Yayınlandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={ProductionOrderStatusEnum.InProgress}>İşlemde</option>
|
{getProductionOrderStatusText(status)}
|
||||||
<option value={ProductionOrderStatusEnum.Completed}>Tamamlandı</option>
|
</option>
|
||||||
<option value={ProductionOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
))}
|
||||||
<option value={ProductionOrderStatusEnum.OnHold}>Beklemede</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -292,10 +298,11 @@ const ProductionOrderForm: React.FC = () => {
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -469,10 +476,11 @@ const ProductionOrderForm: React.FC = () => {
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-yellow-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-yellow-500 transition-all duration-200 bg-gray-50 focus:bg-white"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
<option value="GBP">GBP</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -665,12 +665,11 @@ const ProductionOrderList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={ProductionOrderStatusEnum.Created}>Oluşturuldu</option>
|
{Object.values(ProductionOrderStatusEnum).map((status) => (
|
||||||
<option value={ProductionOrderStatusEnum.Released}>Serbest Bırakıldı</option>
|
<option key={status} value={status}>
|
||||||
<option value={ProductionOrderStatusEnum.InProgress}>Devam Ediyor</option>
|
{getProductionOrderStatusText(status)}
|
||||||
<option value={ProductionOrderStatusEnum.Completed}>Tamamlandı</option>
|
</option>
|
||||||
<option value={ProductionOrderStatusEnum.OnHold}>Beklemede</option>
|
))}
|
||||||
<option value={ProductionOrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -681,10 +680,11 @@ const ProductionOrderList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-2 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
FaChartBar,
|
FaChartBar,
|
||||||
FaDownload,
|
FaDownload,
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import { PsProjectCostTracking } from '../../../types/ps'
|
import { ProjectCostTrackingStatus, PsProjectCostTracking } from '../../../types/ps'
|
||||||
import { mockProjectCostTracking } from '../../../mocks/mockProjectCostTracking'
|
import { mockProjectCostTracking } from '../../../mocks/mockProjectCostTracking'
|
||||||
import Widget from '../../../components/common/Widget'
|
import Widget from '../../../components/common/Widget'
|
||||||
import {
|
import {
|
||||||
|
|
@ -326,10 +326,11 @@ const CostTimeTracking: React.FC = () => {
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="">Tüm Durumlar</option>
|
<option value="">Tüm Durumlar</option>
|
||||||
<option value="ON_TRACK">Planında</option>
|
{Object.values(ProjectCostTrackingStatus).map((status) => (
|
||||||
<option value="AT_RISK">Risk Altında</option>
|
<option key={status} value={status}>
|
||||||
<option value="DELAYED">Gecikmiş</option>
|
{getCostTimeTrackingStatusText(status)}
|
||||||
<option value="COMPLETED">Tamamlandı</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,22 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import {
|
import { FaPlus, FaEdit, FaSave, FaTimesCircle, FaProjectDiagram } from 'react-icons/fa'
|
||||||
FaPlus,
|
|
||||||
FaEdit,
|
|
||||||
FaSave,
|
|
||||||
FaTimesCircle,
|
|
||||||
FaProjectDiagram,
|
|
||||||
} from "react-icons/fa";
|
|
||||||
import {
|
import {
|
||||||
PhaseStatusEnum,
|
PhaseStatusEnum,
|
||||||
PsProjectPhase,
|
PsProjectPhase,
|
||||||
ProjectStatusEnum,
|
ProjectStatusEnum,
|
||||||
} from "../../../types/ps";
|
PhaseCategoryEnum,
|
||||||
import { mockProjects } from "../../../mocks/mockProjects";
|
} from '../../../types/ps'
|
||||||
import { mockProjectPhases } from "../../../mocks/mockProjectPhases";
|
import { mockProjects } from '../../../mocks/mockProjects'
|
||||||
import MultiSelectTeam from "../../../components/common/MultiSelectTeam";
|
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||||
|
import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
|
||||||
|
import { getPhaseCategoryText, getPhaseStatusText } from '@/utils/erp'
|
||||||
|
|
||||||
interface PhaseEditModalProps {
|
interface PhaseEditModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
phase?: PsProjectPhase | null;
|
phase?: PsProjectPhase | null
|
||||||
defaultProjectId?: string;
|
defaultProjectId?: string
|
||||||
onSubmit: (data: PsProjectPhase) => void;
|
onSubmit: (data: PsProjectPhase) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
|
|
@ -30,14 +26,14 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
defaultProjectId,
|
defaultProjectId,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}) => {
|
}) => {
|
||||||
const isEdit = Boolean(phase);
|
const isEdit = Boolean(phase)
|
||||||
|
|
||||||
const ProjectPhaseNew: PsProjectPhase = {
|
const ProjectPhaseNew: PsProjectPhase = {
|
||||||
id: "",
|
id: '',
|
||||||
projectId: defaultProjectId || "",
|
projectId: defaultProjectId || '',
|
||||||
code: "",
|
code: '',
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
startDate: new Date(),
|
startDate: new Date(),
|
||||||
endDate: new Date(),
|
endDate: new Date(),
|
||||||
|
|
@ -52,10 +48,10 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
assignedTeams: [],
|
assignedTeams: [],
|
||||||
deliverables: [],
|
deliverables: [],
|
||||||
risks: [],
|
risks: [],
|
||||||
category: "",
|
category: PhaseCategoryEnum.Planning,
|
||||||
};
|
}
|
||||||
|
|
||||||
const [formData, setFormData] = useState<PsProjectPhase>(ProjectPhaseNew);
|
const [formData, setFormData] = useState<PsProjectPhase>(ProjectPhaseNew)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
|
|
@ -66,50 +62,48 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
name: phase.name,
|
name: phase.name,
|
||||||
projectId: phase.projectId,
|
projectId: phase.projectId,
|
||||||
code: phase.code,
|
code: phase.code,
|
||||||
description: phase.description || "",
|
description: phase.description || '',
|
||||||
status: phase.status,
|
status: phase.status,
|
||||||
startDate: phase.startDate,
|
startDate: phase.startDate,
|
||||||
endDate: phase.endDate,
|
endDate: phase.endDate,
|
||||||
budget: phase.budget,
|
budget: phase.budget,
|
||||||
category: phase.category,
|
category: phase.category,
|
||||||
assignedTeams: phase.assignedTeams || [],
|
assignedTeams: phase.assignedTeams || [],
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
setFormData(ProjectPhaseNew);
|
setFormData(ProjectPhaseNew)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [isOpen, phase, defaultProjectId]);
|
}, [isOpen, phase, defaultProjectId])
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
e: React.ChangeEvent<
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
|
||||||
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
|
||||||
>
|
|
||||||
) => {
|
) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleTeamChange = (teams: string[]) => {
|
const handleTeamChange = (teams: string[]) => {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
assignedTeams: teams,
|
assignedTeams: teams,
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
onSubmit(formData);
|
onSubmit(formData)
|
||||||
};
|
}
|
||||||
|
|
||||||
const generatePhaseCode = () => {
|
const generatePhaseCode = () => {
|
||||||
const phaseCount = mockProjectPhases.length + 1;
|
const phaseCount = mockProjectPhases.length + 1
|
||||||
return `PH-${phaseCount.toString().padStart(3, "0")}`;
|
return `PH-${phaseCount.toString().padStart(3, '0')}`
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
|
@ -126,12 +120,12 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-base font-semibold text-gray-900">
|
<h3 className="text-base font-semibold text-gray-900">
|
||||||
{isEdit ? "Aşama Düzenle" : "Yeni Aşama Oluştur"}
|
{isEdit ? 'Aşama Düzenle' : 'Yeni Aşama Oluştur'}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-xs text-gray-600">
|
<p className="text-xs text-gray-600">
|
||||||
{isEdit
|
{isEdit
|
||||||
? "Mevcut aşama bilgilerini güncelleyin"
|
? 'Mevcut aşama bilgilerini güncelleyin'
|
||||||
: "Yeni bir proje aşaması tanımlayın"}
|
: 'Yeni bir proje aşaması tanımlayın'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -179,9 +173,9 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
{formData.projectId &&
|
{formData.projectId &&
|
||||||
(() => {
|
(() => {
|
||||||
const selectedProject = mockProjects.find(
|
const selectedProject = mockProjects.find(
|
||||||
(p) => p.id === formData.projectId
|
(p) => p.id === formData.projectId,
|
||||||
);
|
)
|
||||||
if (!selectedProject) return null;
|
if (!selectedProject) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-1.5 p-1.5 bg-blue-50 border border-blue-200 rounded-lg">
|
<div className="mt-1.5 p-1.5 bg-blue-50 border border-blue-200 rounded-lg">
|
||||||
|
|
@ -195,79 +189,56 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-2 gap-1.5 text-xs">
|
<div className="grid grid-cols-2 gap-1.5 text-xs">
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium text-blue-800">
|
<span className="font-medium text-blue-800">Durum:</span>
|
||||||
Durum:
|
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
className={`ml-1 px-1.5 py-0.5 rounded-full text-xs font-medium ${
|
className={`ml-1 px-1.5 py-0.5 rounded-full text-xs font-medium ${
|
||||||
selectedProject.status ===
|
selectedProject.status === ProjectStatusEnum.Active
|
||||||
ProjectStatusEnum.Active
|
? 'bg-green-100 text-green-800'
|
||||||
? "bg-green-100 text-green-800"
|
: selectedProject.status === ProjectStatusEnum.Planning
|
||||||
: selectedProject.status ===
|
? 'bg-yellow-100 text-yellow-800'
|
||||||
ProjectStatusEnum.Planning
|
: 'bg-gray-100 text-gray-800'
|
||||||
? "bg-yellow-100 text-yellow-800"
|
|
||||||
: "bg-gray-100 text-gray-800"
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{selectedProject.status ===
|
{selectedProject.status === ProjectStatusEnum.Active
|
||||||
ProjectStatusEnum.Active
|
? 'Aktif'
|
||||||
? "Aktif"
|
: selectedProject.status === ProjectStatusEnum.Planning
|
||||||
: selectedProject.status ===
|
? 'Planlama'
|
||||||
ProjectStatusEnum.Planning
|
: selectedProject.status === ProjectStatusEnum.Completed
|
||||||
? "Planlama"
|
? 'Tamamlandı'
|
||||||
: selectedProject.status ===
|
: selectedProject.status === ProjectStatusEnum.OnHold
|
||||||
ProjectStatusEnum.Completed
|
? 'Beklemede'
|
||||||
? "Tamamlandı"
|
: 'İptal'}
|
||||||
: selectedProject.status ===
|
|
||||||
ProjectStatusEnum.OnHold
|
|
||||||
? "Beklemede"
|
|
||||||
: "İptal"}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium text-blue-800">
|
<span className="font-medium text-blue-800">İlerleme:</span>
|
||||||
İlerleme:
|
|
||||||
</span>
|
|
||||||
<span className="ml-1 text-blue-700">
|
<span className="ml-1 text-blue-700">
|
||||||
%{selectedProject.progress}
|
%{selectedProject.progress}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium text-blue-800">
|
<span className="font-medium text-blue-800">Başlangıç:</span>
|
||||||
Başlangıç:
|
|
||||||
</span>
|
|
||||||
<span className="ml-1 text-blue-700">
|
<span className="ml-1 text-blue-700">
|
||||||
{selectedProject.startDate.toLocaleDateString(
|
{selectedProject.startDate.toLocaleDateString('tr-TR')}
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium text-blue-800">
|
<span className="font-medium text-blue-800">Bitiş:</span>
|
||||||
Bitiş:
|
|
||||||
</span>
|
|
||||||
<span className="ml-1 text-blue-700">
|
<span className="ml-1 text-blue-700">
|
||||||
{selectedProject.endDate.toLocaleDateString(
|
{selectedProject.endDate.toLocaleDateString('tr-TR')}
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1.5 text-right">
|
<div className="ml-1.5 text-right">
|
||||||
<div className="text-base font-bold text-blue-900">
|
<div className="text-base font-bold text-blue-900">
|
||||||
₺
|
₺{selectedProject.budget.toLocaleString('tr-TR')}
|
||||||
{selectedProject.budget.toLocaleString(
|
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-blue-700">
|
|
||||||
Bütçe
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-xs text-blue-700">Bütçe</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -287,9 +258,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama</label>
|
||||||
Açıklama
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
name="description"
|
name="description"
|
||||||
value={formData.description}
|
value={formData.description}
|
||||||
|
|
@ -302,30 +271,18 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||||
Durum
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="status"
|
name="status"
|
||||||
value={formData.status}
|
value={formData.status}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value={PhaseStatusEnum.NotStarted}>
|
{Object.values(PhaseStatusEnum).map((status) => (
|
||||||
Başlanmadı
|
<option key={status} value={status}>
|
||||||
</option>
|
{getPhaseStatusText(status)}
|
||||||
<option value={PhaseStatusEnum.InProgress}>
|
</option>
|
||||||
Devam Ediyor
|
))}
|
||||||
</option>
|
|
||||||
<option value={PhaseStatusEnum.Completed}>
|
|
||||||
Tamamlandı
|
|
||||||
</option>
|
|
||||||
<option value={PhaseStatusEnum.OnHold}>
|
|
||||||
Beklemede
|
|
||||||
</option>
|
|
||||||
<option value={PhaseStatusEnum.Cancelled}>
|
|
||||||
İptal Edildi
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -340,11 +297,11 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value="">Kategori seçin...</option>
|
<option value="">Kategori seçin...</option>
|
||||||
<option value="Planning">Planlama</option>
|
{Object.values(PhaseCategoryEnum).map((cat) => (
|
||||||
<option value="Development">Geliştirme</option>
|
<option key={cat} value={cat}>
|
||||||
<option value="Testing">Test</option>
|
{getPhaseCategoryText(cat)}
|
||||||
<option value="Deployment">Dağıtım</option>
|
</option>
|
||||||
<option value="Design">Tasarım</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -369,7 +326,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
name="startDate"
|
name="startDate"
|
||||||
value={formData.startDate.toISOString().split("T")[0]}
|
value={formData.startDate.toISOString().split('T')[0]}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
/>
|
/>
|
||||||
|
|
@ -382,7 +339,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
name="endDate"
|
name="endDate"
|
||||||
value={formData.endDate.toISOString().split("T")[0]}
|
value={formData.endDate.toISOString().split('T')[0]}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
/>
|
/>
|
||||||
|
|
@ -426,9 +383,7 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
<div className="flex items-center gap-2 text-blue-800">
|
<div className="flex items-center gap-2 text-blue-800">
|
||||||
<FaProjectDiagram className="w-4 h-4" />
|
<FaProjectDiagram className="w-4 h-4" />
|
||||||
<span className="text-sm font-medium">Aşama Kodu:</span>
|
<span className="text-sm font-medium">Aşama Kodu:</span>
|
||||||
<span className="font-bold">
|
<span className="font-bold">{isEdit ? phase?.code : generatePhaseCode()}</span>
|
||||||
{isEdit ? phase?.code : generatePhaseCode()}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -449,13 +404,13 @@ const PhaseEditModal: React.FC<PhaseEditModalProps> = ({
|
||||||
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2 shadow-md hover:shadow-lg"
|
className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2 shadow-md hover:shadow-lg"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{isEdit ? "Güncelle" : "Oluştur"}
|
{isEdit ? 'Güncelle' : 'Oluştur'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default PhaseEditModal;
|
export default PhaseEditModal
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ import {
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
// Custom styles for the slider
|
// Custom styles for the slider
|
||||||
const sliderStyles = `
|
const sliderStyles = `
|
||||||
|
|
@ -810,10 +811,11 @@ const ProjectForm: React.FC = () => {
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<option value="">Tip seçin</option>
|
<option value="">Tip seçin</option>
|
||||||
<option value="INTERNAL">İç Proje</option>
|
{Object.values(ProjectTypeEnum).map((type) => (
|
||||||
<option value="CUSTOMER">Müşteri Projesi</option>
|
<option key={type} value={type}>
|
||||||
<option value="RESEARCH">Ar-Ge Projesi</option>
|
{getProjectTypeText(type)}
|
||||||
<option value="MAINTENANCE">Bakım Projesi</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.projectType && (
|
{errors.projectType && (
|
||||||
<p className="mt-1 text-sm text-red-600">{errors.projectType}</p>
|
<p className="mt-1 text-sm text-red-600">{errors.projectType}</p>
|
||||||
|
|
@ -851,11 +853,11 @@ const ProjectForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('status', e.target.value)}
|
onChange={(e) => handleInputChange('status', e.target.value)}
|
||||||
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="PLANNING">Planlama</option>
|
{Object.values(ProjectStatusEnum).map((status) => (
|
||||||
<option value="ACTIVE">Aktif</option>
|
<option key={status} value={status}>
|
||||||
<option value="ON_HOLD">Beklemede</option>
|
{getProjectStatusText(status)}
|
||||||
<option value="COMPLETED">Tamamlandı</option>
|
</option>
|
||||||
<option value="CANCELLED">İptal Edildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -868,10 +870,11 @@ const ProjectForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('priority', e.target.value)}
|
onChange={(e) => handleInputChange('priority', e.target.value)}
|
||||||
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="LOW">Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value="NORMAL">Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value="HIGH">Yüksek</option>
|
{priority}
|
||||||
<option value="URGENT">Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -884,9 +887,11 @@ const ProjectForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">Türk Lirası (TRY)</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">Amerikan Doları (USD)</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">Euro (EUR)</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1238,9 +1243,11 @@ const ProjectForm: React.FC = () => {
|
||||||
onChange={(e) => handleInputChange('currency', e.target.value)}
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||||||
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="block w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">Türk Lirası (TRY)</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">Amerikan Doları (USD)</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">Euro (EUR)</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,9 @@ import { mockProjects } from '../../../mocks/mockProjects'
|
||||||
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||||
import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
|
import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
import { getPriorityColor, getProjectStatusColor } from '../../../utils/erp'
|
import { getFrequencyUnitText, getGanttStatusColor, getPriorityColor } from '../../../utils/erp'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
import { FrequencyUnitEnum } from '@/types/pm'
|
||||||
|
|
||||||
interface ProjectGanttProps {
|
interface ProjectGanttProps {
|
||||||
employeeId?: string
|
employeeId?: string
|
||||||
|
|
@ -479,7 +480,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
||||||
if (task.type === 'task' && position.isVisible) {
|
if (task.type === 'task' && position.isVisible) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`absolute h-4 sm:h-5 mt-0.5 rounded-sm ${getProjectStatusColor(
|
className={`absolute h-4 sm:h-5 mt-0.5 rounded-sm ${getGanttStatusColor(
|
||||||
task.status,
|
task.status,
|
||||||
)} shadow-md group cursor-pointer border border-white border-opacity-20`}
|
)} shadow-md group cursor-pointer border border-white border-opacity-20`}
|
||||||
style={{ left: position.left, width: position.width }}
|
style={{ left: position.left, width: position.width }}
|
||||||
|
|
@ -546,9 +547,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900">İş Yükü ve Proje Takibi</h2>
|
<h2 className="text-2xl font-bold text-gray-900">İş Yükü ve Proje Takibi</h2>
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600">Tüm görevlerinizi merkezi bir noktadan yönetin.</p>
|
||||||
Tüm görevlerinizi merkezi bir noktadan yönetin.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -592,7 +591,7 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
||||||
<option value="">Tüm Çalışanlar</option>
|
<option value="">Tüm Çalışanlar</option>
|
||||||
{mockEmployees.map((emp) => (
|
{mockEmployees.map((emp) => (
|
||||||
<option key={emp.id} value={emp.id}>
|
<option key={emp.id} value={emp.id}>
|
||||||
{emp.firstName} {emp.lastName}
|
{emp.fullName}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -602,10 +601,18 @@ const ProjectGantt: React.FC<ProjectGanttProps> = ({ employeeId }) => {
|
||||||
onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')}
|
onChange={(e) => setViewMode(e.target.value as 'day' | 'week' | 'month' | 'year')}
|
||||||
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto"
|
className="px-2 py-1.5 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full sm:w-auto"
|
||||||
>
|
>
|
||||||
<option value="day">Günlük</option>
|
<option value={FrequencyUnitEnum.Days}>
|
||||||
<option value="week">Haftalık</option>
|
{getFrequencyUnitText(FrequencyUnitEnum.Days)}
|
||||||
<option value="month">Aylık</option>
|
</option>
|
||||||
<option value="year">Yıllık</option>
|
<option value={FrequencyUnitEnum.Weeks}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Weeks)}
|
||||||
|
</option>
|
||||||
|
<option value={FrequencyUnitEnum.Months}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Months)}
|
||||||
|
</option>
|
||||||
|
<option value={FrequencyUnitEnum.Years}>
|
||||||
|
{getFrequencyUnitText(FrequencyUnitEnum.Years)}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -201,11 +201,11 @@ const ProjectList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={ProjectStatusEnum.Planning}>Planlama</option>
|
{Object.values(ProjectStatusEnum).map((status) => (
|
||||||
<option value={ProjectStatusEnum.Active}>Aktif</option>
|
<option key={status} value={status}>
|
||||||
<option value={ProjectStatusEnum.OnHold}>Beklemede</option>
|
{getProjectStatusText(status)}
|
||||||
<option value={ProjectStatusEnum.Completed}>Tamamlandı</option>
|
</option>
|
||||||
<option value={ProjectStatusEnum.Cancelled}>İptal Edildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -217,10 +217,11 @@ const ProjectList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,12 @@ import {
|
||||||
FaSave,
|
FaSave,
|
||||||
FaProjectDiagram,
|
FaProjectDiagram,
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import { PhaseStatusEnum, PsProjectPhase, ProjectStatusEnum } from '../../../types/ps'
|
import {
|
||||||
|
PhaseStatusEnum,
|
||||||
|
PsProjectPhase,
|
||||||
|
ProjectStatusEnum,
|
||||||
|
PhaseCategoryEnum,
|
||||||
|
} from '../../../types/ps'
|
||||||
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||||
import { mockProjects } from '../../../mocks/mockProjects'
|
import { mockProjects } from '../../../mocks/mockProjects'
|
||||||
import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
|
import MultiSelectTeam from '../../../components/common/MultiSelectTeam'
|
||||||
|
|
@ -23,6 +28,8 @@ import {
|
||||||
getPhaseStatusIcon,
|
getPhaseStatusIcon,
|
||||||
getPhaseStatusText,
|
getPhaseStatusText,
|
||||||
getPhaseStatusColor,
|
getPhaseStatusColor,
|
||||||
|
getProjectStatusText,
|
||||||
|
getPhaseCategoryText,
|
||||||
} from '../../../utils/erp'
|
} from '../../../utils/erp'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
|
|
||||||
|
|
@ -45,7 +52,7 @@ const ProjectPhases: React.FC = () => {
|
||||||
startDate: '',
|
startDate: '',
|
||||||
endDate: '',
|
endDate: '',
|
||||||
budget: 0,
|
budget: 0,
|
||||||
category: '',
|
category: PhaseCategoryEnum.Planning,
|
||||||
assignedTeams: [] as string[],
|
assignedTeams: [] as string[],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -93,7 +100,7 @@ const ProjectPhases: React.FC = () => {
|
||||||
startDate: '',
|
startDate: '',
|
||||||
endDate: '',
|
endDate: '',
|
||||||
budget: 0,
|
budget: 0,
|
||||||
category: '',
|
category: PhaseCategoryEnum.Planning,
|
||||||
assignedTeams: [],
|
assignedTeams: [],
|
||||||
})
|
})
|
||||||
setIsCreateModalOpen(true)
|
setIsCreateModalOpen(true)
|
||||||
|
|
@ -247,11 +254,11 @@ const ProjectPhases: React.FC = () => {
|
||||||
className="px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500"
|
className="px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="All">Tüm Durumlar</option>
|
<option value="All">Tüm Durumlar</option>
|
||||||
<option value={ProjectStatusEnum.Planning}>Başlanmadı</option>
|
{Object.values(ProjectStatusEnum).map((status) => (
|
||||||
<option value={ProjectStatusEnum.Active}>Devam Ediyor</option>
|
<option key={status} value={status}>
|
||||||
<option value={ProjectStatusEnum.OnHold}>Beklemede</option>
|
{getProjectStatusText(status)}
|
||||||
<option value={ProjectStatusEnum.Completed}>Tamamlandı</option>
|
</option>
|
||||||
<option value={ProjectStatusEnum.Cancelled}>İptal Edildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -862,11 +869,11 @@ const ProjectPhases: React.FC = () => {
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value="">Kategori seçin...</option>
|
<option value="">Kategori seçin...</option>
|
||||||
<option value="Planning">Planlama</option>
|
{Object.values(PhaseCategoryEnum).map((cat) => (
|
||||||
<option value="Development">Geliştirme</option>
|
<option key={cat} value={cat}>
|
||||||
<option value="Testing">Test</option>
|
{getPhaseCategoryText(cat)}
|
||||||
<option value="Deployment">Dağıtım</option>
|
</option>
|
||||||
<option value="Design">Tasarım</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -880,11 +887,11 @@ const ProjectPhases: React.FC = () => {
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value={PhaseStatusEnum.NotStarted}>Başlanmadı</option>
|
{Object.values(PhaseStatusEnum).map((status) => (
|
||||||
<option value={PhaseStatusEnum.InProgress}>Devam Ediyor</option>
|
<option key={status} value={status}>
|
||||||
<option value={PhaseStatusEnum.Completed}>Tamamlandı</option>
|
{getPhaseStatusText(status)}
|
||||||
<option value={PhaseStatusEnum.OnHold}>Beklemede</option>
|
</option>
|
||||||
<option value={PhaseStatusEnum.Cancelled}>İptal Edildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from 'react'
|
||||||
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from "../../../types/ps";
|
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from '../../../types/ps'
|
||||||
import {
|
import {
|
||||||
FaSearch,
|
FaSearch,
|
||||||
FaPlus,
|
FaPlus,
|
||||||
|
|
@ -13,158 +13,157 @@ import {
|
||||||
FaFlag,
|
FaFlag,
|
||||||
FaProjectDiagram,
|
FaProjectDiagram,
|
||||||
FaUserCog,
|
FaUserCog,
|
||||||
} from "react-icons/fa";
|
} from 'react-icons/fa'
|
||||||
import { mockProjectTasks } from "../../../mocks/mockProjectTasks";
|
import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
|
||||||
import { mockEmployees } from "../../../mocks/mockEmployees";
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { mockProjects } from "../../../mocks/mockProjects";
|
import { mockProjects } from '../../../mocks/mockProjects'
|
||||||
import { mockProjectPhases } from "../../../mocks/mockProjectPhases";
|
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||||
import Widget from "../../../components/common/Widget";
|
import Widget from '../../../components/common/Widget'
|
||||||
import { PriorityEnum } from "../../../types/common";
|
import { PriorityEnum } from '../../../types/common'
|
||||||
import {
|
import {
|
||||||
getTaskStatusColor,
|
getTaskStatusColor,
|
||||||
getTaskStatusIcon,
|
getTaskStatusIcon,
|
||||||
getPriorityColor,
|
getPriorityColor,
|
||||||
getTaskTypeColor,
|
getTaskTypeColor,
|
||||||
} from "../../../utils/erp";
|
getPriorityText,
|
||||||
import { Container } from "@/components/shared";
|
getTaskStatusText,
|
||||||
|
getTaskTypeText,
|
||||||
|
} from '../../../utils/erp'
|
||||||
|
import { Container } from '@/components/shared'
|
||||||
|
|
||||||
const ProjectTasks: React.FC = () => {
|
const ProjectTasks: React.FC = () => {
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [statusFilter, setStatusFilter] = useState<TaskStatusEnum | "">("");
|
const [statusFilter, setStatusFilter] = useState<TaskStatusEnum | ''>('')
|
||||||
const [selectedProjectFilter, setSelectedProjectFilter] = useState("All");
|
const [selectedProjectFilter, setSelectedProjectFilter] = useState('All')
|
||||||
const [selectedTask, setSelectedTask] = useState<PsProjectTask | null>(null);
|
const [selectedTask, setSelectedTask] = useState<PsProjectTask | null>(null)
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false)
|
||||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
const [isEditModalOpen, setIsEditModalOpen] = useState(false)
|
||||||
const [editingTask, setEditingTask] = useState<PsProjectTask | null>(null);
|
const [editingTask, setEditingTask] = useState<PsProjectTask | null>(null)
|
||||||
|
|
||||||
// Form state for creating/editing tasks
|
// Form state for creating/editing tasks
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
projectId: "",
|
projectId: '',
|
||||||
phaseId: "",
|
phaseId: '',
|
||||||
taskType: TaskTypeEnum.Development,
|
taskType: TaskTypeEnum.Development,
|
||||||
status: TaskStatusEnum.NotStarted,
|
status: TaskStatusEnum.NotStarted,
|
||||||
priority: PriorityEnum.Normal,
|
priority: PriorityEnum.Normal,
|
||||||
assignedTo: "",
|
assignedTo: '',
|
||||||
assigneeEmail: "",
|
assigneeEmail: '',
|
||||||
startDate: "",
|
startDate: '',
|
||||||
endDate: "",
|
endDate: '',
|
||||||
estimatedHours: 0,
|
estimatedHours: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
});
|
})
|
||||||
|
|
||||||
const filteredTasks = mockProjectTasks.filter((task) => {
|
const filteredTasks = mockProjectTasks.filter((task) => {
|
||||||
const matchesSearch =
|
const matchesSearch =
|
||||||
task.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
task.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
task.taskCode.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
task.taskCode.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
(task.description &&
|
(task.description && task.description.toLowerCase().includes(searchTerm.toLowerCase()))
|
||||||
task.description.toLowerCase().includes(searchTerm.toLowerCase()));
|
const matchesStatus = statusFilter === '' || task.status === statusFilter
|
||||||
const matchesStatus = statusFilter === "" || task.status === statusFilter;
|
|
||||||
const matchesProject =
|
const matchesProject =
|
||||||
selectedProjectFilter === "All" ||
|
selectedProjectFilter === 'All' || task.projectId === selectedProjectFilter
|
||||||
task.projectId === selectedProjectFilter;
|
return matchesSearch && matchesStatus && matchesProject
|
||||||
return matchesSearch && matchesStatus && matchesProject;
|
})
|
||||||
});
|
|
||||||
|
|
||||||
const openModal = (task: PsProjectTask) => {
|
const openModal = (task: PsProjectTask) => {
|
||||||
setSelectedTask(task);
|
setSelectedTask(task)
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true)
|
||||||
};
|
}
|
||||||
|
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
setSelectedTask(null);
|
setSelectedTask(null)
|
||||||
setIsModalOpen(false);
|
setIsModalOpen(false)
|
||||||
};
|
}
|
||||||
|
|
||||||
const openCreateModal = () => {
|
const openCreateModal = () => {
|
||||||
setFormData({
|
setFormData({
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
projectId: "",
|
projectId: '',
|
||||||
phaseId: "",
|
phaseId: '',
|
||||||
taskType: TaskTypeEnum.Development,
|
taskType: TaskTypeEnum.Development,
|
||||||
status: TaskStatusEnum.NotStarted,
|
status: TaskStatusEnum.NotStarted,
|
||||||
priority: PriorityEnum.Normal,
|
priority: PriorityEnum.Normal,
|
||||||
assignedTo: "",
|
assignedTo: '',
|
||||||
assigneeEmail: "",
|
assigneeEmail: '',
|
||||||
startDate: "",
|
startDate: '',
|
||||||
endDate: "",
|
endDate: '',
|
||||||
estimatedHours: 0,
|
estimatedHours: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
});
|
})
|
||||||
setIsCreateModalOpen(true);
|
setIsCreateModalOpen(true)
|
||||||
};
|
}
|
||||||
|
|
||||||
const closeCreateModal = () => {
|
const closeCreateModal = () => {
|
||||||
setIsCreateModalOpen(false);
|
setIsCreateModalOpen(false)
|
||||||
};
|
}
|
||||||
|
|
||||||
const openEditModal = (task: PsProjectTask) => {
|
const openEditModal = (task: PsProjectTask) => {
|
||||||
setEditingTask(task);
|
setEditingTask(task)
|
||||||
setFormData({
|
setFormData({
|
||||||
name: task.name,
|
name: task.name,
|
||||||
description: task.description || "",
|
description: task.description || '',
|
||||||
projectId: task.projectId || "",
|
projectId: task.projectId || '',
|
||||||
phaseId: task.phaseId || "",
|
phaseId: task.phaseId || '',
|
||||||
taskType: task.taskType,
|
taskType: task.taskType,
|
||||||
status: task.status,
|
status: task.status,
|
||||||
priority: task.priority,
|
priority: task.priority,
|
||||||
assignedTo: task.assignedTo || "",
|
assignedTo: task.assignedTo || '',
|
||||||
assigneeEmail: task.assignee?.email || "",
|
assigneeEmail: task.assignee?.email || '',
|
||||||
startDate: task.startDate.toISOString().split("T")[0],
|
startDate: task.startDate.toISOString().split('T')[0],
|
||||||
endDate: task.endDate.toISOString().split("T")[0],
|
endDate: task.endDate.toISOString().split('T')[0],
|
||||||
estimatedHours: task.estimatedHours,
|
estimatedHours: task.estimatedHours,
|
||||||
progress: task.progress,
|
progress: task.progress,
|
||||||
});
|
})
|
||||||
setIsEditModalOpen(true);
|
setIsEditModalOpen(true)
|
||||||
};
|
}
|
||||||
|
|
||||||
const closeEditModal = () => {
|
const closeEditModal = () => {
|
||||||
setIsEditModalOpen(false);
|
setIsEditModalOpen(false)
|
||||||
setEditingTask(null);
|
setEditingTask(null)
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
e: React.ChangeEvent<
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
|
||||||
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
|
||||||
>
|
|
||||||
) => {
|
) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target
|
||||||
|
|
||||||
// Eğer atanan kişi seçimi yapılıyorsa, e-posta adresini otomatik doldur
|
// Eğer atanan kişi seçimi yapılıyorsa, e-posta adresini otomatik doldur
|
||||||
if (name === "assignedTo") {
|
if (name === 'assignedTo') {
|
||||||
const selectedEmployee = mockEmployees.find((emp) => emp.id === value);
|
const selectedEmployee = mockEmployees.find((emp) => emp.id === value)
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
assigneeEmail: selectedEmployee?.email || "",
|
assigneeEmail: selectedEmployee?.email || '',
|
||||||
}));
|
}))
|
||||||
} else {
|
} else {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
// Here you would normally save to backend
|
// Here you would normally save to backend
|
||||||
console.log("Saving task:", formData);
|
console.log('Saving task:', formData)
|
||||||
alert(isEditModalOpen ? "Görev güncellendi!" : "Yeni görev oluşturuldu!");
|
alert(isEditModalOpen ? 'Görev güncellendi!' : 'Yeni görev oluşturuldu!')
|
||||||
if (isEditModalOpen) {
|
if (isEditModalOpen) {
|
||||||
closeEditModal();
|
closeEditModal()
|
||||||
} else {
|
} else {
|
||||||
closeCreateModal();
|
closeCreateModal()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const generateTaskCode = () => {
|
const generateTaskCode = () => {
|
||||||
const taskCount = mockProjectTasks.length + 1;
|
const taskCount = mockProjectTasks.length + 1
|
||||||
return `TSK-${taskCount.toString().padStart(3, "0")}`;
|
return `TSK-${taskCount.toString().padStart(3, '0')}`
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
|
@ -172,9 +171,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Görev Yönetimi</h2>
|
<h2 className="text-2xl font-bold text-gray-900">Görev Yönetimi</h2>
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600">Proje görevlerinizi oluşturun, düzenleyin ve takip edin</p>
|
||||||
Proje görevlerinizi oluşturun, düzenleyin ve takip edin
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={openCreateModal}
|
onClick={openCreateModal}
|
||||||
|
|
@ -196,22 +193,14 @@ const ProjectTasks: React.FC = () => {
|
||||||
|
|
||||||
<Widget
|
<Widget
|
||||||
title="Devam Eden"
|
title="Devam Eden"
|
||||||
value={
|
value={mockProjectTasks.filter((t) => t.status === TaskStatusEnum.InProgress).length}
|
||||||
mockProjectTasks.filter(
|
|
||||||
(t) => t.status === TaskStatusEnum.InProgress
|
|
||||||
).length
|
|
||||||
}
|
|
||||||
color="yellow"
|
color="yellow"
|
||||||
icon="FaClock"
|
icon="FaClock"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Widget
|
<Widget
|
||||||
title="Tamamlanan"
|
title="Tamamlanan"
|
||||||
value={
|
value={mockProjectTasks.filter((t) => t.status === TaskStatusEnum.Completed).length}
|
||||||
mockProjectTasks.filter(
|
|
||||||
(t) => t.status === TaskStatusEnum.Completed
|
|
||||||
).length
|
|
||||||
}
|
|
||||||
color="green"
|
color="green"
|
||||||
icon="FaCheckCircle"
|
icon="FaCheckCircle"
|
||||||
/>
|
/>
|
||||||
|
|
@ -222,9 +211,9 @@ const ProjectTasks: React.FC = () => {
|
||||||
mockProjectTasks.length > 0
|
mockProjectTasks.length > 0
|
||||||
? `${Math.round(
|
? `${Math.round(
|
||||||
mockProjectTasks.reduce((sum, t) => sum + t.progress, 0) /
|
mockProjectTasks.reduce((sum, t) => sum + t.progress, 0) /
|
||||||
mockProjectTasks.length
|
mockProjectTasks.length,
|
||||||
)}%`
|
)}%`
|
||||||
: "0%"
|
: '0%'
|
||||||
}
|
}
|
||||||
color="red"
|
color="red"
|
||||||
icon="FaBullseye"
|
icon="FaBullseye"
|
||||||
|
|
@ -260,17 +249,15 @@ const ProjectTasks: React.FC = () => {
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={statusFilter}
|
value={statusFilter}
|
||||||
onChange={(e) =>
|
onChange={(e) => setStatusFilter(e.target.value as TaskStatusEnum | '')}
|
||||||
setStatusFilter(e.target.value as TaskStatusEnum | "")
|
|
||||||
}
|
|
||||||
className="w-full px-2.5 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-2.5 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="">Tüm Durumlar</option>
|
<option value="">Tüm Durumlar</option>
|
||||||
<option value={TaskStatusEnum.NotStarted}>Başlanmadı</option>
|
{Object.values(TaskStatusEnum).map((status) => (
|
||||||
<option value={TaskStatusEnum.InProgress}>Devam Ediyor</option>
|
<option key={status} value={status}>
|
||||||
<option value={TaskStatusEnum.Completed}>Tamamlandı</option>
|
{getTaskStatusText(status)}
|
||||||
<option value={TaskStatusEnum.OnHold}>Beklemede</option>
|
</option>
|
||||||
<option value={TaskStatusEnum.Cancelled}>İptal Edildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -316,25 +303,21 @@ const ProjectTasks: React.FC = () => {
|
||||||
<tr
|
<tr
|
||||||
key={task.id}
|
key={task.id}
|
||||||
className={`hover:bg-blue-50 transition-colors duration-200 ${
|
className={`hover:bg-blue-50 transition-colors duration-200 ${
|
||||||
index % 2 === 0 ? "bg-white" : "bg-gray-50"
|
index % 2 === 0 ? 'bg-white' : 'bg-gray-50'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<td className="px-2 py-1 whitespace-nowrap">
|
<td className="px-2 py-1 whitespace-nowrap">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-medium text-blue-700">
|
<div className="text-sm font-medium text-blue-700">
|
||||||
{(() => {
|
{(() => {
|
||||||
const project = mockProjects.find(
|
const project = mockProjects.find((p) => p.id === task.projectId)
|
||||||
(p) => p.id === task.projectId
|
return project?.name || `Proje ID: ${task.projectId}`
|
||||||
);
|
|
||||||
return project?.name || `Proje ID: ${task.projectId}`;
|
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-gray-500">
|
<div className="text-xs text-gray-500">
|
||||||
{(() => {
|
{(() => {
|
||||||
const project = mockProjects.find(
|
const project = mockProjects.find((p) => p.id === task.projectId)
|
||||||
(p) => p.id === task.projectId
|
return project?.code || task.projectId
|
||||||
);
|
|
||||||
return project?.code || task.projectId;
|
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -344,19 +327,15 @@ const ProjectTasks: React.FC = () => {
|
||||||
<div className="text-sm font-medium text-green-700">
|
<div className="text-sm font-medium text-green-700">
|
||||||
{task.phase?.name ||
|
{task.phase?.name ||
|
||||||
(() => {
|
(() => {
|
||||||
const phase = mockProjectPhases.find(
|
const phase = mockProjectPhases.find((p) => p.id === task.phaseId)
|
||||||
(p) => p.id === task.phaseId
|
return phase?.name || `Aşama ID: ${task.phaseId}`
|
||||||
);
|
|
||||||
return phase?.name || `Aşama ID: ${task.phaseId}`;
|
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-gray-500">
|
<div className="text-xs text-gray-500">
|
||||||
{task.phase?.code ||
|
{task.phase?.code ||
|
||||||
(() => {
|
(() => {
|
||||||
const phase = mockProjectPhases.find(
|
const phase = mockProjectPhases.find((p) => p.id === task.phaseId)
|
||||||
(p) => p.id === task.phaseId
|
return phase?.code || task.phaseId
|
||||||
);
|
|
||||||
return phase?.code || task.phaseId;
|
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -375,7 +354,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
<td className="px-2 py-1 whitespace-nowrap">
|
<td className="px-2 py-1 whitespace-nowrap">
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-xs font-semibold ${getTaskStatusColor(
|
className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-xs font-semibold ${getTaskStatusColor(
|
||||||
task.status
|
task.status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getTaskStatusIcon(task.status)}
|
{getTaskStatusIcon(task.status)}
|
||||||
|
|
@ -385,7 +364,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
<td className="px-2 py-1 whitespace-nowrap">
|
<td className="px-2 py-1 whitespace-nowrap">
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-semibold ${getPriorityColor(
|
className={`inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-semibold ${getPriorityColor(
|
||||||
task.priority
|
task.priority,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{task.priority}
|
{task.priority}
|
||||||
|
|
@ -397,7 +376,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
<FaUser className="w-4 h-4 text-blue-600" />
|
<FaUser className="w-4 h-4 text-blue-600" />
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-900 font-medium">
|
<div className="text-sm text-gray-900 font-medium">
|
||||||
{task.assignee?.fullName || "-"}
|
{task.assignee?.fullName || '-'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -415,7 +394,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2 py-1 whitespace-nowrap text-sm text-gray-900 font-medium">
|
<td className="px-2 py-1 whitespace-nowrap text-sm text-gray-900 font-medium">
|
||||||
{task.endDate.toLocaleDateString("tr-TR")}
|
{task.endDate.toLocaleDateString('tr-TR')}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2 py-1 whitespace-nowrap text-sm font-medium">
|
<td className="px-2 py-1 whitespace-nowrap text-sm font-medium">
|
||||||
<div className="flex gap-1 justify-center">
|
<div className="flex gap-1 justify-center">
|
||||||
|
|
@ -446,12 +425,9 @@ const ProjectTasks: React.FC = () => {
|
||||||
<div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-2">
|
<div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-2">
|
||||||
<FaBullseye className="w-6 h-6 text-gray-400" />
|
<FaBullseye className="w-6 h-6 text-gray-400" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-base font-medium text-gray-900 mb-1">
|
<h3 className="text-base font-medium text-gray-900 mb-1">Görev bulunamadı</h3>
|
||||||
Görev bulunamadı
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-500">
|
<p className="text-gray-500">
|
||||||
Arama kriterlerinizi değiştirmeyi deneyin veya yeni bir görev
|
Arama kriterlerinizi değiştirmeyi deneyin veya yeni bir görev oluşturun.
|
||||||
oluşturun.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -500,20 +476,17 @@ const ProjectTasks: React.FC = () => {
|
||||||
<div className="text-sm font-semibold text-blue-800">
|
<div className="text-sm font-semibold text-blue-800">
|
||||||
{(() => {
|
{(() => {
|
||||||
const project = mockProjects.find(
|
const project = mockProjects.find(
|
||||||
(p) => p.id === selectedTask.projectId
|
(p) => p.id === selectedTask.projectId,
|
||||||
);
|
)
|
||||||
return (
|
return project?.name || `Proje ID: ${selectedTask.projectId}`
|
||||||
project?.name ||
|
|
||||||
`Proje ID: ${selectedTask.projectId}`
|
|
||||||
);
|
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-blue-600 mt-1">
|
<div className="text-xs text-blue-600 mt-1">
|
||||||
{(() => {
|
{(() => {
|
||||||
const project = mockProjects.find(
|
const project = mockProjects.find(
|
||||||
(p) => p.id === selectedTask.projectId
|
(p) => p.id === selectedTask.projectId,
|
||||||
);
|
)
|
||||||
return project?.code || selectedTask.projectId;
|
return project?.code || selectedTask.projectId
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -528,21 +501,18 @@ const ProjectTasks: React.FC = () => {
|
||||||
{selectedTask.phase?.name ||
|
{selectedTask.phase?.name ||
|
||||||
(() => {
|
(() => {
|
||||||
const phase = mockProjectPhases.find(
|
const phase = mockProjectPhases.find(
|
||||||
(p) => p.id === selectedTask.phaseId
|
(p) => p.id === selectedTask.phaseId,
|
||||||
);
|
)
|
||||||
return (
|
return phase?.name || `Aşama ID: ${selectedTask.phaseId}`
|
||||||
phase?.name ||
|
|
||||||
`Aşama ID: ${selectedTask.phaseId}`
|
|
||||||
);
|
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-green-600 mt-1">
|
<div className="text-xs text-green-600 mt-1">
|
||||||
{selectedTask.phase?.code ||
|
{selectedTask.phase?.code ||
|
||||||
(() => {
|
(() => {
|
||||||
const phase = mockProjectPhases.find(
|
const phase = mockProjectPhases.find(
|
||||||
(p) => p.id === selectedTask.phaseId
|
(p) => p.id === selectedTask.phaseId,
|
||||||
);
|
)
|
||||||
return phase?.code || selectedTask.phaseId;
|
return phase?.code || selectedTask.phaseId
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -554,7 +524,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
Açıklama
|
Açıklama
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-900 bg-white p-2 rounded-lg border">
|
<p className="text-sm text-gray-900 bg-white p-2 rounded-lg border">
|
||||||
{selectedTask.description || "Açıklama bulunmuyor."}
|
{selectedTask.description || 'Açıklama bulunmuyor.'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -565,7 +535,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getTaskTypeColor(
|
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getTaskTypeColor(
|
||||||
selectedTask.taskType
|
selectedTask.taskType,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{selectedTask.taskType}
|
{selectedTask.taskType}
|
||||||
|
|
@ -577,7 +547,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-lg text-xs font-semibold ${getTaskStatusColor(
|
className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-lg text-xs font-semibold ${getTaskStatusColor(
|
||||||
selectedTask.status
|
selectedTask.status,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getTaskStatusIcon(selectedTask.status)}
|
{getTaskStatusIcon(selectedTask.status)}
|
||||||
|
|
@ -592,7 +562,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getPriorityColor(
|
className={`inline-flex items-center px-2 py-1 rounded-lg text-xs font-semibold ${getPriorityColor(
|
||||||
selectedTask.priority
|
selectedTask.priority,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{selectedTask.priority}
|
{selectedTask.priority}
|
||||||
|
|
@ -612,9 +582,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
<p className="text-sm font-medium text-gray-900">
|
<p className="text-sm font-medium text-gray-900">
|
||||||
{selectedTask.assignee.fullName}
|
{selectedTask.assignee.fullName}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">{selectedTask.assignee.email}</p>
|
||||||
{selectedTask.assignee.email}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -641,7 +609,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
Planlanan Başlangıç
|
Planlanan Başlangıç
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-900 font-medium">
|
<p className="text-sm text-gray-900 font-medium">
|
||||||
{selectedTask.startDate.toLocaleDateString("tr-TR")}
|
{selectedTask.startDate.toLocaleDateString('tr-TR')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white p-2 rounded-lg border">
|
<div className="bg-white p-2 rounded-lg border">
|
||||||
|
|
@ -649,9 +617,8 @@ const ProjectTasks: React.FC = () => {
|
||||||
Gerçek Başlangıç
|
Gerçek Başlangıç
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-900 font-medium">
|
<p className="text-sm text-gray-900 font-medium">
|
||||||
{selectedTask.actualStartDate?.toLocaleDateString(
|
{selectedTask.actualStartDate?.toLocaleDateString('tr-TR') ||
|
||||||
"tr-TR"
|
'Henüz başlanmadı'}
|
||||||
) || "Henüz başlanmadı"}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -662,7 +629,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
Planlanan Bitiş
|
Planlanan Bitiş
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-900 font-medium">
|
<p className="text-sm text-gray-900 font-medium">
|
||||||
{selectedTask.endDate.toLocaleDateString("tr-TR")}
|
{selectedTask.endDate.toLocaleDateString('tr-TR')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white p-2 rounded-lg border">
|
<div className="bg-white p-2 rounded-lg border">
|
||||||
|
|
@ -670,9 +637,8 @@ const ProjectTasks: React.FC = () => {
|
||||||
Gerçek Bitiş
|
Gerçek Bitiş
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-900 font-medium">
|
<p className="text-sm text-gray-900 font-medium">
|
||||||
{selectedTask.actualEndDate?.toLocaleDateString(
|
{selectedTask.actualEndDate?.toLocaleDateString('tr-TR') ||
|
||||||
"tr-TR"
|
'Henüz tamamlanmadı'}
|
||||||
) || "Henüz tamamlanmadı"}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -727,9 +693,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
Oluşturulma
|
Oluşturulma
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
{selectedTask.creationTime.toLocaleDateString(
|
{selectedTask.creationTime.toLocaleDateString('tr-TR')}
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -737,9 +701,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
Son Güncelleme
|
Son Güncelleme
|
||||||
</label>
|
</label>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
{selectedTask.lastModificationTime.toLocaleDateString(
|
{selectedTask.lastModificationTime.toLocaleDateString('tr-TR')}
|
||||||
"tr-TR"
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -759,8 +721,8 @@ const ProjectTasks: React.FC = () => {
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
closeModal();
|
closeModal()
|
||||||
openEditModal(selectedTask!);
|
openEditModal(selectedTask!)
|
||||||
}}
|
}}
|
||||||
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-sm"
|
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-sm"
|
||||||
>
|
>
|
||||||
|
|
@ -788,12 +750,12 @@ const ProjectTasks: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-bold text-gray-900">
|
<h3 className="text-lg font-bold text-gray-900">
|
||||||
{isEditModalOpen ? "Görev Düzenle" : "Yeni Görev Oluştur"}
|
{isEditModalOpen ? 'Görev Düzenle' : 'Yeni Görev Oluştur'}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-xs text-gray-600">
|
<p className="text-xs text-gray-600">
|
||||||
{isEditModalOpen
|
{isEditModalOpen
|
||||||
? "Mevcut görev bilgilerini güncelleyin"
|
? 'Mevcut görev bilgilerini güncelleyin'
|
||||||
: "Yeni bir görev tanımlayın"}
|
: 'Yeni bir görev tanımlayın'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -850,16 +812,11 @@ const ProjectTasks: React.FC = () => {
|
||||||
disabled={!formData.projectId}
|
disabled={!formData.projectId}
|
||||||
>
|
>
|
||||||
<option value="">
|
<option value="">
|
||||||
{formData.projectId
|
{formData.projectId ? 'Aşama seçin...' : 'Önce proje seçin'}
|
||||||
? "Aşama seçin..."
|
|
||||||
: "Önce proje seçin"}
|
|
||||||
</option>
|
</option>
|
||||||
{formData.projectId &&
|
{formData.projectId &&
|
||||||
mockProjectPhases
|
mockProjectPhases
|
||||||
.filter(
|
.filter((phase) => phase.projectId === formData.projectId)
|
||||||
(phase) =>
|
|
||||||
phase.projectId === formData.projectId
|
|
||||||
)
|
|
||||||
.map((phase) => (
|
.map((phase) => (
|
||||||
<option key={phase.id} value={phase.id}>
|
<option key={phase.id} value={phase.id}>
|
||||||
{phase.code} - {phase.name}
|
{phase.code} - {phase.name}
|
||||||
|
|
@ -907,18 +864,11 @@ const ProjectTasks: React.FC = () => {
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value={TaskTypeEnum.Development}>
|
{Object.values(TaskTypeEnum).map((type) => (
|
||||||
Geliştirme
|
<option key={type} value={type}>
|
||||||
</option>
|
{getTaskTypeText(type)}
|
||||||
<option value={TaskTypeEnum.Testing}>Test</option>
|
</option>
|
||||||
<option value={TaskTypeEnum.Documentation}>
|
))}
|
||||||
Dokümantasyon
|
|
||||||
</option>
|
|
||||||
<option value={TaskTypeEnum.Review}>İnceleme</option>
|
|
||||||
<option value={TaskTypeEnum.Deployment}>
|
|
||||||
Dağıtım
|
|
||||||
</option>
|
|
||||||
<option value={TaskTypeEnum.Meeting}>Toplantı</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -932,10 +882,11 @@ const ProjectTasks: React.FC = () => {
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -949,21 +900,11 @@ const ProjectTasks: React.FC = () => {
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
className="w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
||||||
>
|
>
|
||||||
<option value={TaskStatusEnum.NotStarted}>
|
{Object.values(TaskStatusEnum).map((status) => (
|
||||||
Başlanmadı
|
<option key={status} value={status}>
|
||||||
</option>
|
{getTaskStatusText(status)}
|
||||||
<option value={TaskStatusEnum.InProgress}>
|
</option>
|
||||||
Devam Ediyor
|
))}
|
||||||
</option>
|
|
||||||
<option value={TaskStatusEnum.Completed}>
|
|
||||||
Tamamlandı
|
|
||||||
</option>
|
|
||||||
<option value={TaskStatusEnum.OnHold}>
|
|
||||||
Beklemede
|
|
||||||
</option>
|
|
||||||
<option value={TaskStatusEnum.Cancelled}>
|
|
||||||
İptal Edildi
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -994,8 +935,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
.filter((emp) => emp.isActive)
|
.filter((emp) => emp.isActive)
|
||||||
.map((employee) => (
|
.map((employee) => (
|
||||||
<option key={employee.id} value={employee.id}>
|
<option key={employee.id} value={employee.id}>
|
||||||
{employee.fullName} -{" "}
|
{employee.fullName} - {employee.jobPosition?.name}
|
||||||
{employee.jobPosition?.name}
|
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -1021,8 +961,8 @@ const ProjectTasks: React.FC = () => {
|
||||||
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200">
|
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200">
|
||||||
{(() => {
|
{(() => {
|
||||||
const selectedEmployee = mockEmployees.find(
|
const selectedEmployee = mockEmployees.find(
|
||||||
(emp) => emp.id === formData.assignedTo
|
(emp) => emp.id === formData.assignedTo,
|
||||||
);
|
)
|
||||||
return selectedEmployee ? (
|
return selectedEmployee ? (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center">
|
<div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center">
|
||||||
|
|
@ -1040,7 +980,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -1126,9 +1066,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
<FaFlag className="w-4 h-4" />
|
<FaFlag className="w-4 h-4" />
|
||||||
<span className="text-sm font-medium">Görev Kodu:</span>
|
<span className="text-sm font-medium">Görev Kodu:</span>
|
||||||
<span className="font-bold">
|
<span className="font-bold">
|
||||||
{isEditModalOpen
|
{isEditModalOpen ? editingTask?.taskCode : generateTaskCode()}
|
||||||
? editingTask?.taskCode
|
|
||||||
: generateTaskCode()}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1150,7 +1088,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md"
|
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{isEditModalOpen ? "Güncelle" : "Oluştur"}
|
{isEditModalOpen ? 'Güncelle' : 'Oluştur'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -1158,8 +1096,7 @@ const ProjectTasks: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
);
|
export default ProjectTasks
|
||||||
};
|
|
||||||
|
|
||||||
export default ProjectTasks;
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from 'react'
|
||||||
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from "../../../types/ps";
|
import { PsProjectTask, TaskTypeEnum, TaskStatusEnum } from '../../../types/ps'
|
||||||
import {
|
import {
|
||||||
FaPlus,
|
FaPlus,
|
||||||
FaEdit,
|
FaEdit,
|
||||||
|
|
@ -10,39 +10,40 @@ import {
|
||||||
FaUserCog,
|
FaUserCog,
|
||||||
FaSave,
|
FaSave,
|
||||||
FaTimesCircle,
|
FaTimesCircle,
|
||||||
} from "react-icons/fa";
|
} from 'react-icons/fa'
|
||||||
import { mockEmployees } from "../../../mocks/mockEmployees";
|
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||||
import { mockProjects } from "../../../mocks/mockProjects";
|
import { mockProjects } from '../../../mocks/mockProjects'
|
||||||
import { mockProjectPhases } from "../../../mocks/mockProjectPhases";
|
import { mockProjectPhases } from '../../../mocks/mockProjectPhases'
|
||||||
import { PriorityEnum } from "../../../types/common";
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { getPriorityText, getTaskStatusText, getTaskTypeText } from '@/utils/erp'
|
||||||
|
|
||||||
export interface TaskFormData {
|
export interface TaskFormData {
|
||||||
name: string;
|
name: string
|
||||||
description: string;
|
description: string
|
||||||
projectId: string;
|
projectId: string
|
||||||
phaseId: string;
|
phaseId: string
|
||||||
taskType: TaskTypeEnum;
|
taskType: TaskTypeEnum
|
||||||
status: TaskStatusEnum;
|
status: TaskStatusEnum
|
||||||
priority: PriorityEnum;
|
priority: PriorityEnum
|
||||||
assignedTo: string;
|
assignedTo: string
|
||||||
assigneeEmail: string;
|
assigneeEmail: string
|
||||||
startDate: string;
|
startDate: string
|
||||||
endDate: string;
|
endDate: string
|
||||||
estimatedHours: number;
|
estimatedHours: number
|
||||||
progress: number;
|
progress: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TaskEditModalProps {
|
interface TaskEditModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
task?: PsProjectTask | null;
|
task?: PsProjectTask | null
|
||||||
onSubmit: (taskData: TaskFormData) => void;
|
onSubmit: (taskData: TaskFormData) => void
|
||||||
mode: "create" | "edit";
|
mode: 'create' | 'edit'
|
||||||
defaultProjectId?: string;
|
defaultProjectId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputClasses =
|
const inputClasses =
|
||||||
"w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors";
|
'w-full px-2.5 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors'
|
||||||
|
|
||||||
const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
|
|
@ -53,91 +54,89 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
defaultProjectId,
|
defaultProjectId,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState<TaskFormData>({
|
const [formData, setFormData] = useState<TaskFormData>({
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
projectId: "",
|
projectId: '',
|
||||||
phaseId: "",
|
phaseId: '',
|
||||||
taskType: TaskTypeEnum.Development,
|
taskType: TaskTypeEnum.Development,
|
||||||
status: TaskStatusEnum.NotStarted,
|
status: TaskStatusEnum.NotStarted,
|
||||||
priority: PriorityEnum.Normal,
|
priority: PriorityEnum.Normal,
|
||||||
assignedTo: "",
|
assignedTo: '',
|
||||||
assigneeEmail: "",
|
assigneeEmail: '',
|
||||||
startDate: "",
|
startDate: '',
|
||||||
endDate: "",
|
endDate: '',
|
||||||
estimatedHours: 0,
|
estimatedHours: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
});
|
})
|
||||||
|
|
||||||
const generateTaskCode = () => {
|
const generateTaskCode = () => {
|
||||||
const taskCount = 1; // Bu gerçek uygulamada dinamik olarak hesaplanmalı
|
const taskCount = 1 // Bu gerçek uygulamada dinamik olarak hesaplanmalı
|
||||||
return `TSK-${taskCount.toString().padStart(3, "0")}`;
|
return `TSK-${taskCount.toString().padStart(3, '0')}`
|
||||||
};
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mode === "edit" && task) {
|
if (mode === 'edit' && task) {
|
||||||
setFormData({
|
setFormData({
|
||||||
name: task.name,
|
name: task.name,
|
||||||
description: task.description || "",
|
description: task.description || '',
|
||||||
projectId: task.projectId,
|
projectId: task.projectId,
|
||||||
phaseId: task.phaseId || "",
|
phaseId: task.phaseId || '',
|
||||||
taskType: task.taskType,
|
taskType: task.taskType,
|
||||||
status: task.status,
|
status: task.status,
|
||||||
priority: task.priority,
|
priority: task.priority,
|
||||||
assignedTo: task.assignedTo || "",
|
assignedTo: task.assignedTo || '',
|
||||||
assigneeEmail: task.assignee?.email || "",
|
assigneeEmail: task.assignee?.email || '',
|
||||||
startDate: task.startDate.toISOString().split("T")[0],
|
startDate: task.startDate.toISOString().split('T')[0],
|
||||||
endDate: task.endDate.toISOString().split("T")[0],
|
endDate: task.endDate.toISOString().split('T')[0],
|
||||||
estimatedHours: task.estimatedHours,
|
estimatedHours: task.estimatedHours,
|
||||||
progress: task.progress,
|
progress: task.progress,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
// Reset form for create mode
|
// Reset form for create mode
|
||||||
setFormData({
|
setFormData({
|
||||||
name: "",
|
name: '',
|
||||||
description: "",
|
description: '',
|
||||||
projectId: defaultProjectId || "",
|
projectId: defaultProjectId || '',
|
||||||
phaseId: "",
|
phaseId: '',
|
||||||
taskType: TaskTypeEnum.Development,
|
taskType: TaskTypeEnum.Development,
|
||||||
status: TaskStatusEnum.NotStarted,
|
status: TaskStatusEnum.NotStarted,
|
||||||
priority: PriorityEnum.Normal,
|
priority: PriorityEnum.Normal,
|
||||||
assignedTo: "",
|
assignedTo: '',
|
||||||
assigneeEmail: "",
|
assigneeEmail: '',
|
||||||
startDate: "",
|
startDate: '',
|
||||||
endDate: "",
|
endDate: '',
|
||||||
estimatedHours: 0,
|
estimatedHours: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}, [mode, task, isOpen, defaultProjectId]);
|
}, [mode, task, isOpen, defaultProjectId])
|
||||||
|
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
e: React.ChangeEvent<
|
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
||||||
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
||||||
>
|
|
||||||
) => {
|
) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// Auto-fill email when employee is selected
|
// Auto-fill email when employee is selected
|
||||||
if (name === "assignedTo") {
|
if (name === 'assignedTo') {
|
||||||
const selectedEmployee = mockEmployees.find((emp) => emp.id === value);
|
const selectedEmployee = mockEmployees.find((emp) => emp.id === value)
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
assigneeEmail: selectedEmployee?.email || "",
|
assigneeEmail: selectedEmployee?.email || '',
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
onSubmit(formData);
|
onSubmit(formData)
|
||||||
onClose();
|
onClose()
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
|
@ -146,7 +145,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
<div className="flex items-center justify-between p-2.5 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-t-xl">
|
<div className="flex items-center justify-between p-2.5 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-t-xl">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="w-6 h-6 bg-blue-600 rounded-md flex items-center justify-center">
|
<div className="w-6 h-6 bg-blue-600 rounded-md flex items-center justify-center">
|
||||||
{mode === "edit" ? (
|
{mode === 'edit' ? (
|
||||||
<FaEdit className="w-3.5 h-3.5 text-white" />
|
<FaEdit className="w-3.5 h-3.5 text-white" />
|
||||||
) : (
|
) : (
|
||||||
<FaPlus className="w-3.5 h-3.5 text-white" />
|
<FaPlus className="w-3.5 h-3.5 text-white" />
|
||||||
|
|
@ -154,12 +153,12 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-bold text-gray-900">
|
<h3 className="text-lg font-bold text-gray-900">
|
||||||
{mode === "edit" ? "Görev Düzenle" : "Yeni Görev Oluştur"}
|
{mode === 'edit' ? 'Görev Düzenle' : 'Yeni Görev Oluştur'}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-xs text-gray-600">
|
<p className="text-xs text-gray-600">
|
||||||
{mode === "edit"
|
{mode === 'edit'
|
||||||
? "Mevcut görev bilgilerini güncelleyin"
|
? 'Mevcut görev bilgilerini güncelleyin'
|
||||||
: "Yeni bir görev tanımlayın"}
|
: 'Yeni bir görev tanımlayın'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -217,15 +216,11 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
disabled={!formData.projectId}
|
disabled={!formData.projectId}
|
||||||
>
|
>
|
||||||
<option value="">
|
<option value="">
|
||||||
{formData.projectId
|
{formData.projectId ? 'Aşama seçin...' : 'Önce proje seçin'}
|
||||||
? "Aşama seçin..."
|
|
||||||
: "Önce proje seçin"}
|
|
||||||
</option>
|
</option>
|
||||||
{formData.projectId &&
|
{formData.projectId &&
|
||||||
mockProjectPhases
|
mockProjectPhases
|
||||||
.filter(
|
.filter((phase) => phase.projectId === formData.projectId)
|
||||||
(phase) => phase.projectId === formData.projectId
|
|
||||||
)
|
|
||||||
.map((phase) => (
|
.map((phase) => (
|
||||||
<option key={phase.id} value={phase.id}>
|
<option key={phase.id} value={phase.id}>
|
||||||
{phase.code} - {phase.name}
|
{phase.code} - {phase.name}
|
||||||
|
|
@ -250,9 +245,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Açıklama</label>
|
||||||
Açıklama
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
name="description"
|
name="description"
|
||||||
value={formData.description}
|
value={formData.description}
|
||||||
|
|
@ -273,59 +266,43 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={inputClasses}
|
className={inputClasses}
|
||||||
>
|
>
|
||||||
<option value={TaskTypeEnum.Development}>
|
{Object.values(TaskTypeEnum).map((type) => (
|
||||||
Geliştirme
|
<option key={type} value={type}>
|
||||||
</option>
|
{getTaskTypeText(type)}
|
||||||
<option value={TaskTypeEnum.Testing}>Test</option>
|
</option>
|
||||||
<option value={TaskTypeEnum.Documentation}>
|
))}
|
||||||
Dokümantasyon
|
|
||||||
</option>
|
|
||||||
<option value={TaskTypeEnum.Review}>İnceleme</option>
|
|
||||||
<option value={TaskTypeEnum.Deployment}>Dağıtım</option>
|
|
||||||
<option value={TaskTypeEnum.Meeting}>Toplantı</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Öncelik</label>
|
||||||
Öncelik
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="priority"
|
name="priority"
|
||||||
value={formData.priority}
|
value={formData.priority}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={inputClasses}
|
className={inputClasses}
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
|
||||||
Durum
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
name="status"
|
name="status"
|
||||||
value={formData.status}
|
value={formData.status}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={inputClasses}
|
className={inputClasses}
|
||||||
>
|
>
|
||||||
<option value={TaskStatusEnum.NotStarted}>
|
{Object.values(TaskStatusEnum).map((status) => (
|
||||||
Başlanmadı
|
<option key={status} value={status}>
|
||||||
</option>
|
{getTaskStatusText(status)}
|
||||||
<option value={TaskStatusEnum.InProgress}>
|
</option>
|
||||||
Devam Ediyor
|
))}
|
||||||
</option>
|
|
||||||
<option value={TaskStatusEnum.Completed}>
|
|
||||||
Tamamlandı
|
|
||||||
</option>
|
|
||||||
<option value={TaskStatusEnum.OnHold}>Beklemede</option>
|
|
||||||
<option value={TaskStatusEnum.Cancelled}>
|
|
||||||
İptal Edildi
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -363,9 +340,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
|
||||||
E-posta
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
name="assigneeEmail"
|
name="assigneeEmail"
|
||||||
|
|
@ -381,8 +356,8 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
{formData.assignedTo &&
|
{formData.assignedTo &&
|
||||||
(() => {
|
(() => {
|
||||||
const selectedEmployee = mockEmployees.find(
|
const selectedEmployee = mockEmployees.find(
|
||||||
(emp) => emp.id === formData.assignedTo
|
(emp) => emp.id === formData.assignedTo,
|
||||||
);
|
)
|
||||||
return selectedEmployee ? (
|
return selectedEmployee ? (
|
||||||
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200 flex items-center gap-2">
|
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200 flex items-center gap-2">
|
||||||
<div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center shrink-0">
|
<div className="w-10 h-10 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center shrink-0">
|
||||||
|
|
@ -400,7 +375,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-2.5">
|
<div className="grid grid-cols-2 gap-2.5">
|
||||||
|
|
@ -448,7 +423,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{mode === "edit" && (
|
{mode === 'edit' && (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
İlerleme (%)
|
İlerleme (%)
|
||||||
|
|
@ -484,7 +459,7 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
<FaFlag className="w-4 h-4" />
|
<FaFlag className="w-4 h-4" />
|
||||||
<span className="text-sm font-medium">Görev Kodu:</span>
|
<span className="text-sm font-medium">Görev Kodu:</span>
|
||||||
<span className="font-bold">
|
<span className="font-bold">
|
||||||
{mode === "edit" ? task?.taskCode : generateTaskCode()}
|
{mode === 'edit' ? task?.taskCode : generateTaskCode()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -506,13 +481,13 @@ const TaskEditModal: React.FC<TaskEditModalProps> = ({
|
||||||
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md hover:shadow-lg"
|
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-1.5 shadow-md hover:shadow-lg"
|
||||||
>
|
>
|
||||||
<FaSave className="w-4 h-4" />
|
<FaSave className="w-4 h-4" />
|
||||||
{mode === "edit" ? "Güncelle" : "Oluştur"}
|
{mode === 'edit' ? 'Güncelle' : 'Oluştur'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default TaskEditModal;
|
export default TaskEditModal
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from '../../../types/mm'
|
} from '../../../types/mm'
|
||||||
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee'
|
||||||
import { mockDepartments } from '../../../mocks/mockDepartments'
|
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||||
|
import { getApprovalLevelText, getRequestTypeText } from '@/utils/erp'
|
||||||
|
|
||||||
interface ApprovalWorkflowModalProps {
|
interface ApprovalWorkflowModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -195,10 +196,11 @@ const ApprovalWorkflowModal: React.FC<ApprovalWorkflowModalProps> = ({
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={RequestTypeEnum.Material}>Malzeme</option>
|
{Object.values(RequestTypeEnum).map((type) => (
|
||||||
<option value={RequestTypeEnum.Service}>Hizmet</option>
|
<option key={type} value={type}>
|
||||||
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option>
|
{getRequestTypeText(type)}
|
||||||
<option value={RequestTypeEnum.Maintenance}>Bakım</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -276,14 +278,11 @@ const ApprovalWorkflowModal: React.FC<ApprovalWorkflowModalProps> = ({
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={ApprovalLevelEnum.Supervisor}>Süpervizör</option>
|
{Object.values(ApprovalLevelEnum).map((lvl) => (
|
||||||
<option value={ApprovalLevelEnum.Manager}>Müdür</option>
|
<option key={lvl} value={lvl}>
|
||||||
<option value={ApprovalLevelEnum.Director}>Direktör</option>
|
{getApprovalLevelText(lvl)}
|
||||||
<option value={ApprovalLevelEnum.GeneralManager}>Genel Müdür</option>
|
</option>
|
||||||
<option value={ApprovalLevelEnum.FinanceManager}>
|
))}
|
||||||
Mali İşler Müdürü
|
|
||||||
</option>
|
|
||||||
<option value={ApprovalLevelEnum.TechnicalManager}>Teknik Müdür</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -210,15 +210,11 @@ const DeliveryTracking: React.FC = () => {
|
||||||
className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={DeliveryStatusEnum.Preparing}>Hazırlanıyor</option>
|
{Object.values(DeliveryStatusEnum).map((status) => (
|
||||||
<option value={DeliveryStatusEnum.Shipped}>Kargoya Verildi</option>
|
<option key={status} value={status}>
|
||||||
<option value={DeliveryStatusEnum.InTransit}>Yolda</option>
|
{getDeliveryStatusText(status)}
|
||||||
<option value={DeliveryStatusEnum.OutForDelivery}>Dağıtımda</option>
|
</option>
|
||||||
<option value={DeliveryStatusEnum.Delivered}>Teslim Edildi</option>
|
))}
|
||||||
<option value={DeliveryStatusEnum.PartiallyDelivered}>Kısmi Teslim</option>
|
|
||||||
<option value={DeliveryStatusEnum.Delayed}>Gecikmeli</option>
|
|
||||||
<option value={DeliveryStatusEnum.Returned}>İade Edildi</option>
|
|
||||||
<option value={DeliveryStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ import {
|
||||||
QualityStatusEnum,
|
QualityStatusEnum,
|
||||||
MmGoodsReceiptItem,
|
MmGoodsReceiptItem,
|
||||||
} from '../../../types/mm'
|
} from '../../../types/mm'
|
||||||
|
import { mock } from 'node:test'
|
||||||
|
import { mockWarehouses } from '@/mocks/mockWarehouses'
|
||||||
|
import { getQualityStatusText, getReceiptStatusText } from '@/utils/erp'
|
||||||
|
|
||||||
interface DeliveryTrackingModalProps {
|
interface DeliveryTrackingModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -226,10 +229,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<option value="">Depo Seçiniz</option>
|
<option value="">Depo Seçiniz</option>
|
||||||
<option value="WH001">Ana Depo</option>
|
{mockWarehouses.map((wh) => (
|
||||||
<option value="WH002">Hammadde Deposu</option>
|
<option key={wh.id} value={wh.id}>
|
||||||
<option value="WH003">Mamul Deposu</option>
|
{wh.name}
|
||||||
<option value="WH004">Yedek Parça Deposu</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -242,10 +246,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={ReceiptStatusEnum.Pending}>Beklemede</option>
|
{Object.values(ReceiptStatusEnum).map((status) => (
|
||||||
<option value={ReceiptStatusEnum.InProgress}>İşlemde</option>
|
<option key={status} value={status}>
|
||||||
<option value={ReceiptStatusEnum.Completed}>Tamamlandı</option>
|
{getReceiptStatusText(status)}
|
||||||
<option value={ReceiptStatusEnum.OnHold}>Bekletildi</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -402,10 +407,11 @@ const DeliveryTrackingModal: React.FC<DeliveryTrackingModalProps> = ({
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full text-sm border border-gray-300 rounded-md px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={QualityStatusEnum.Pending}>Beklemede</option>
|
{Object.values(QualityStatusEnum).map((status) => (
|
||||||
<option value={QualityStatusEnum.Approved}>Kabul</option>
|
<option key={status} value={status}>
|
||||||
<option value={QualityStatusEnum.Rejected}>Red</option>
|
{getQualityStatusText(status)}
|
||||||
<option value={QualityStatusEnum.Conditional}>Koşullu</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { MaterialTypeEnum, MmMaterialType } from '@/types/mm'
|
import { MaterialTypeEnum, MmMaterialType } from '@/types/mm'
|
||||||
|
import { getMaterialTypeText } from '@/utils/erp'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
interface MaterialTypeModalProps {
|
interface MaterialTypeModalProps {
|
||||||
|
|
@ -43,12 +44,11 @@ const MaterialTypeModal: React.FC<MaterialTypeModalProps> = ({ type, onSave, onC
|
||||||
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<option value={MaterialTypeEnum.RawMaterial}>Hammadde</option>
|
{Object.values(MaterialTypeEnum).map((value) => (
|
||||||
<option value={MaterialTypeEnum.SemiFinished}>Yarı Mamul</option>
|
<option key={value} value={value}>
|
||||||
<option value={MaterialTypeEnum.Finished}>Mamul</option>
|
{getMaterialTypeText(value)}
|
||||||
<option value={MaterialTypeEnum.Consumable}>Sarf Malzemesi</option>
|
</option>
|
||||||
<option value={MaterialTypeEnum.Service}>Hizmet</option>
|
))}
|
||||||
<option value={MaterialTypeEnum.Spare}>Yedek Parça</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react'
|
||||||
import { FaPlus, FaEdit, FaTrash, FaSearch, FaTh, FaList } from 'react-icons/fa'
|
import { FaPlus, FaEdit, FaTrash, FaSearch, FaTh, FaList } from 'react-icons/fa'
|
||||||
import { MmMaterialType, MaterialTypeEnum } from '../../../types/mm'
|
import { MmMaterialType, MaterialTypeEnum } from '../../../types/mm'
|
||||||
import { mockMaterialTypes } from '../../../mocks/mockMaterialTypes'
|
import { mockMaterialTypes } from '../../../mocks/mockMaterialTypes'
|
||||||
import { getMaterialTypeDisplay } from '../../../utils/erp'
|
import { getMaterialTypeText } from '../../../utils/erp'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import MaterialTypeModal from './MaterialTypeModal'
|
import MaterialTypeModal from './MaterialTypeModal'
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ const MaterialTypes: React.FC = () => {
|
||||||
<tr key={type.id} className="hover:bg-gray-50 text-xs">
|
<tr key={type.id} className="hover:bg-gray-50 text-xs">
|
||||||
<td className="px-3 py-1.5 whitespace-nowrap">
|
<td className="px-3 py-1.5 whitespace-nowrap">
|
||||||
<span className="text-sm font-mono font-medium text-gray-900">
|
<span className="text-sm font-mono font-medium text-gray-900">
|
||||||
{getMaterialTypeDisplay(type.code)}
|
{getMaterialTypeText(type.code)}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5 whitespace-nowrap">
|
<td className="px-3 py-1.5 whitespace-nowrap">
|
||||||
|
|
@ -206,7 +206,7 @@ const MaterialTypes: React.FC = () => {
|
||||||
<div className="flex items-start justify-between mb-3">
|
<div className="flex items-start justify-between mb-3">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<span className="text-xs font-mono font-medium text-blue-600 bg-blue-50 px-2 py-1 rounded">
|
<span className="text-xs font-mono font-medium text-blue-600 bg-blue-50 px-2 py-1 rounded">
|
||||||
{getMaterialTypeDisplay(type.code)}
|
{getMaterialTypeText(type.code)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-1">
|
<div className="flex items-center space-x-1">
|
||||||
|
|
|
||||||
|
|
@ -195,15 +195,11 @@ const OrderManagement: React.FC = () => {
|
||||||
className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="pl-10 pr-4 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="all">Tüm Durumlar</option>
|
<option value="all">Tüm Durumlar</option>
|
||||||
<option value={OrderStatusEnum.Draft}>Taslak</option>
|
{Object.values(OrderStatusEnum).map((status) => (
|
||||||
<option value={OrderStatusEnum.Pending}>Beklemede</option>
|
<option key={status} value={status}>
|
||||||
<option value={OrderStatusEnum.Approved}>Onaylandı</option>
|
{getOrderStatusText(status)}
|
||||||
<option value={OrderStatusEnum.Sent}>Gönderildi</option>
|
</option>
|
||||||
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option>
|
))}
|
||||||
<option value={OrderStatusEnum.PartiallyDelivered}>Kısmi Teslim</option>
|
|
||||||
<option value={OrderStatusEnum.Delivered}>Teslim Edildi</option>
|
|
||||||
<option value={OrderStatusEnum.Completed}>Tamamlandı</option>
|
|
||||||
<option value={OrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -559,14 +555,11 @@ const OrderManagement: React.FC = () => {
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
>
|
>
|
||||||
<option value="">Durum Seçiniz</option>
|
<option value="">Durum Seçiniz</option>
|
||||||
<option value={OrderStatusEnum.Pending}>Beklemede</option>
|
{Object.values(OrderStatusEnum).map((status) => (
|
||||||
<option value={OrderStatusEnum.Approved}>Onaylandı</option>
|
<option key={status} value={status}>
|
||||||
<option value={OrderStatusEnum.Sent}>Gönderildi</option>
|
{getOrderStatusText(status)}
|
||||||
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option>
|
</option>
|
||||||
<option value={OrderStatusEnum.PartiallyDelivered}>Kısmi Teslim</option>
|
))}
|
||||||
<option value={OrderStatusEnum.Delivered}>Teslim Edildi</option>
|
|
||||||
<option value={OrderStatusEnum.Completed}>Tamamlandı</option>
|
|
||||||
<option value={OrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ import { mockPurchaseOrders } from '../../../mocks/mockPurchaseOrders'
|
||||||
import { Address, PaymentTerms } from '../../../types/common'
|
import { Address, PaymentTerms } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { getOrderStatusText, getPaymentTermsText } from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
const OrderManagementForm: React.FC = () => {
|
const OrderManagementForm: React.FC = () => {
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
|
|
@ -318,14 +320,11 @@ const OrderManagementForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PaymentTerms.Net15}>15 Gün Vadeli</option>
|
{Object.values(PaymentTerms).map((term) => (
|
||||||
<option value={PaymentTerms.Net30}>30 Gün Vadeli</option>
|
<option key={term} value={term}>
|
||||||
<option value={PaymentTerms.Net45}>45 Gün Vadeli</option>
|
{getPaymentTermsText(term)}
|
||||||
<option value={PaymentTerms.Net60}>60 Gün Vadeli</option>
|
</option>
|
||||||
<option value={PaymentTerms.Net90}>90 Gün Vadeli</option>
|
))}
|
||||||
<option value={PaymentTerms.COD}>Kapıda Ödeme</option>
|
|
||||||
<option value={PaymentTerms.Prepaid}>Peşin</option>
|
|
||||||
<option value={PaymentTerms.Cash}>Nakit</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -338,9 +337,11 @@ const OrderManagementForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -654,14 +655,11 @@ const OrderManagementForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={OrderStatusEnum.Draft}>Taslak</option>
|
{Object.values(OrderStatusEnum).map((status) => (
|
||||||
<option value={OrderStatusEnum.Sent}>Gönderildi</option>
|
<option key={status} value={status}>
|
||||||
<option value={OrderStatusEnum.Confirmed}>Onaylandı</option>
|
{getOrderStatusText(status)}
|
||||||
<option value={OrderStatusEnum.PartiallyReceived}>Kısmi Teslim</option>
|
</option>
|
||||||
<option value={OrderStatusEnum.Received}>Teslim Alındı</option>
|
))}
|
||||||
<option value={OrderStatusEnum.Invoiced}>Faturalandı</option>
|
|
||||||
<option value={OrderStatusEnum.Closed}>Kapatıldı</option>
|
|
||||||
<option value={OrderStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import { mockPurchaseRequests } from '../../../mocks/mockPurchaseRequests'
|
||||||
import { PriorityEnum } from '../../../types/common'
|
import { PriorityEnum } from '../../../types/common'
|
||||||
import { Container } from '@/components/shared'
|
import { Container } from '@/components/shared'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { getPriorityText, getRequestStatusText, getRequestTypeText } from '@/utils/erp'
|
||||||
|
import { mockCurrencies } from '@/mocks/mockCurrencies'
|
||||||
|
|
||||||
const PurchaseRequestForm: React.FC = () => {
|
const PurchaseRequestForm: React.FC = () => {
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
|
|
@ -198,10 +200,11 @@ const PurchaseRequestForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={RequestTypeEnum.Material}>Malzeme</option>
|
{Object.values(RequestTypeEnum).map((type) => (
|
||||||
<option value={RequestTypeEnum.Service}>Hizmet</option>
|
<option key={type} value={type}>
|
||||||
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option>
|
{getRequestTypeText(type)}
|
||||||
<option value={RequestTypeEnum.Maintenance}>Bakım</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -294,10 +297,11 @@ const PurchaseRequestForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -310,9 +314,11 @@ const PurchaseRequestForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="TRY">TRY</option>
|
{mockCurrencies.map((currency) => (
|
||||||
<option value="USD">USD</option>
|
<option key={currency.value} value={currency.value}>
|
||||||
<option value="EUR">EUR</option>
|
{currency.value} - {currency.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -500,12 +506,11 @@ const PurchaseRequestForm: React.FC = () => {
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="mt-1 block w-full border border-gray-300 rounded-md px-2.5 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value={RequestStatusEnum.Draft}>Taslak</option>
|
{Object.values(RequestStatusEnum).map((status) => (
|
||||||
<option value={RequestStatusEnum.Submitted}>Gönderildi</option>
|
<option key={status} value={status}>
|
||||||
<option value={RequestStatusEnum.InReview}>İncelemede</option>
|
{getRequestStatusText(status)}
|
||||||
<option value={RequestStatusEnum.Approved}>Onaylandı</option>
|
</option>
|
||||||
<option value={RequestStatusEnum.Rejected}>Reddedildi</option>
|
))}
|
||||||
<option value={RequestStatusEnum.Cancelled}>İptal Edildi</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,23 +96,24 @@ const PurchaseRequests: React.FC = () => {
|
||||||
onChange={(e) => setFilterStatus(e.target.value as RequestStatusEnum | 'ALL')}
|
onChange={(e) => setFilterStatus(e.target.value as RequestStatusEnum | 'ALL')}
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="ALL">Tüm Durumlar</option>
|
<option value="All">Tüm Durumlar</option>
|
||||||
<option value={RequestStatusEnum.Draft}>Taslak</option>
|
{Object.values(RequestStatusEnum).map((status) => (
|
||||||
<option value={RequestStatusEnum.Submitted}>Gönderildi</option>
|
<option key={status} value={status}>
|
||||||
<option value={RequestStatusEnum.InReview}>İnceleniyor</option>
|
{getRequestStatusText(status)}
|
||||||
<option value={RequestStatusEnum.Approved}>Onaylandı</option>
|
</option>
|
||||||
<option value={RequestStatusEnum.Rejected}>Reddedildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
<select
|
<select
|
||||||
value={filterType}
|
value={filterType}
|
||||||
onChange={(e) => setFilterType(e.target.value as RequestTypeEnum | 'ALL')}
|
onChange={(e) => setFilterType(e.target.value as RequestTypeEnum | 'ALL')}
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
>
|
>
|
||||||
<option value="ALL">Tüm Türler</option>
|
<option value="All">Tüm Türler</option>
|
||||||
<option value={RequestTypeEnum.Material}>Malzeme</option>
|
{Object.values(RequestTypeEnum).map((type) => (
|
||||||
<option value={RequestTypeEnum.Service}>Hizmet</option>
|
<option key={type} value={type}>
|
||||||
<option value={RequestTypeEnum.WorkCenter}>İş Merkezi</option>
|
{getRequestTypeText(type)}
|
||||||
<option value={RequestTypeEnum.Maintenance}>Bakım</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,11 +141,11 @@ const PurchaseRequisitionList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={RequisitionStatusEnum.Draft}>Taslak</option>
|
{Object.values(RequisitionStatusEnum).map((status) => (
|
||||||
<option value={RequisitionStatusEnum.Submitted}>Gönderildi</option>
|
<option key={status} value={status}>
|
||||||
<option value={RequisitionStatusEnum.InApproval}>Onayda</option>
|
{getRequisitionStatusText(status)}
|
||||||
<option value={RequisitionStatusEnum.Approved}>Onaylandı</option>
|
</option>
|
||||||
<option value={RequisitionStatusEnum.Rejected}>Reddedildi</option>
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -157,10 +157,11 @@ const PurchaseRequisitionList: React.FC = () => {
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
<option value="all">Tümü</option>
|
<option value="all">Tümü</option>
|
||||||
<option value={PriorityEnum.Low}>Düşük</option>
|
{Object.values(PriorityEnum).map((priority) => (
|
||||||
<option value={PriorityEnum.Normal}>Normal</option>
|
<option key={priority} value={priority}>
|
||||||
<option value={PriorityEnum.High}>Yüksek</option>
|
{getPriorityText(priority)}
|
||||||
<option value={PriorityEnum.Urgent}>Acil</option>
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue