diff --git a/api/modules/Sozsoft.Languages/Sozsoft.Languages.Application/LanguagesApplicationMappers.cs b/api/modules/Sozsoft.Languages/Sozsoft.Languages.Application/LanguagesApplicationMappers.cs index 0bad436..acb2ebc 100644 --- a/api/modules/Sozsoft.Languages/Sozsoft.Languages.Application/LanguagesApplicationMappers.cs +++ b/api/modules/Sozsoft.Languages/Sozsoft.Languages.Application/LanguagesApplicationMappers.cs @@ -107,9 +107,31 @@ public partial class LanguageTextCreateUpdateDtoToLanguageTextMapper : MapperBas public partial class LanguageKeyToLanguageTextTranslatedDtoMapper : MapperBase { [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.Id))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseCultureName))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseValue))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetCultureName))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetValue))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.IsDeleted))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeleterId))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeletionTime))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModificationTime))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModifierId))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreationTime))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreatorId))] public override partial LanguageTextTranslatedDto Map(LanguageKey source); [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.Id))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseCultureName))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseValue))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetCultureName))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetValue))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.IsDeleted))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeleterId))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeletionTime))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModificationTime))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModifierId))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreationTime))] + [MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreatorId))] public override partial void Map(LanguageKey source, LanguageTextTranslatedDto destination); public override void BeforeMap(LanguageKey source) diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index 7f82db4..0a0597f 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -1542,12 +1542,6 @@ "en": "Charts", "tr": "Grafikler" }, - { - "resourceName": "Platform", - "key": "App.Listforms.ImportManager.Uploading", - "en": "Uploading...", - "tr": "Yükleniyor..." - }, { "resourceName": "Platform", "key": "App.Listforms.ImportManager.Validating", @@ -8252,37 +8246,37 @@ }, { "resourceName": "Platform", - "key": "Public.cart.title", + "key": "Public.basket.title", "tr": "Sepetim", - "en": "My Cart" + "en": "My Basket" }, { "resourceName": "Platform", - "key": "Public.cart.clearConfirm", + "key": "Public.basket.clearConfirm", "tr": "Sepetteki tüm ürünleri silmek istediğinizden emin misiniz?", - "en": "Are you sure you want to remove all items from the cart?" + "en": "Are you sure you want to remove all items from the basket?" }, { "resourceName": "Platform", - "key": "Public.cart.clear", + "key": "Public.basket.clear", "tr": "Sepeti Temizle", - "en": "Clear Cart" + "en": "Clear Basket" }, { "resourceName": "Platform", - "key": "Public.cart.empty.title", + "key": "Public.basket.empty.title", "tr": "Sepetiniz boş", - "en": "Your cart is empty" + "en": "Your basket is empty" }, { "resourceName": "Platform", - "key": "Public.cart.empty.subtitle", + "key": "Public.basket.empty.subtitle", "tr": "Ürün eklemek için katalogdan seçim yapın", "en": "Add products from the catalog" }, { "resourceName": "Platform", - "key": "Public.cart.checkout", + "key": "Public.basket.checkout", "tr": "Ödemeye Geç", "en": "Proceed to Checkout" }, @@ -8324,15 +8318,15 @@ }, { "resourceName": "Platform", - "key": "Public.products.addToCart", + "key": "Public.products.addToBasket", "tr": "Sepete Ekle", - "en": "Add to Cart" + "en": "Add to Basket" }, { "resourceName": "Platform", - "key": "Public.products.inCart", + "key": "Public.products.inBasket", "tr": "Sepette Mevcut", - "en": "Already in Cart" + "en": "Already in Basket" }, { "resourceName": "Platform", @@ -11634,12 +11628,6 @@ "tr": "Değiştir", "en": "Replace" }, - { - "resourceName": "Platform", - "key": "App.Platform.Loading", - "tr": "Yükleniyor...", - "en": "Loading..." - }, { "resourceName": "Platform", "key": "App.Platform.FailedtoloadDatasources", @@ -12258,12 +12246,6 @@ "tr": "Farklı filtreler deneyin veya yeni bir kayıt ekleyin.", "en": "Try different filters or add a new record." }, - { - "resourceName": "Platform", - "key": "App.Platform.Card.Loading", - "tr": "Yükleniyor...", - "en": "Loading..." - }, { "resourceName": "Platform", "key": "App.Platform.Card.TotalRecords", @@ -17490,6 +17472,18 @@ "en": "Website", "tr": "Web Sitesi" }, + { + "resourceName": "Platform", + "key": "App.WebSite.PatternError", + "en": "Invalid website URL", + "tr": "Geçersiz web sitesi adresi" + }, + { + "resourceName": "Platform", + "key": "App.Email.PatternError", + "en": "Invalid email address", + "tr": "Geçersiz email adresi" + }, { "resourceName": "Platform", "key": "App.Listform.ListformField.Wednesday", @@ -18306,12 +18300,6 @@ "en": "Select icon...", "tr": "İkon seç..." }, - { - "resourceName": "Platform", - "key": "ListForms.Wizard.Step2.Loading", - "en": "Loading...", - "tr": "Yükleniyor..." - }, { "resourceName": "Platform", "key": "ListForms.Wizard.Step2.SelectKeyColumn", @@ -18642,12 +18630,6 @@ "en": "e.g. Product, User, Order", "tr": "örn. Product, User, Order" }, - { - "resourceName": "Platform", - "key": "App.SqlQueryManager.Loading", - "en": "Loading...", - "tr": "Yükleniyor..." - }, { "resourceName": "Platform", "key": "App.SqlQueryManager.LoadingFkConstraints", @@ -18912,12 +18894,6 @@ "en": "Data source of the CRUD endpoints", "tr": "CRUD endpointlerinin veri kaynağı" }, - { - "resourceName": "Platform", - "key": "App.DeveloperKit.CrudEndpoints.Loading", - "en": "Loading...", - "tr": "Yükleniyor..." - }, { "resourceName": "Platform", "key": "App.DeveloperKit.CrudEndpoints.SearchTable", diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json index 9b01524..98a07f6 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json @@ -509,132 +509,11 @@ "IsDisabled": false, "ShortName": "Sas" }, - { - "ParentCode": "App.Saas", - "Code": "App.Public", - "DisplayName": "App.Public", - "Order": 1, - "Url": null, - "Icon": "FcTemplate", - "RequiredPermissionName": null, - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Home", - "DisplayName": "App.Home", - "Order": 0, - "Url": "/admin/public/home/designer", - "Icon": "FcHome", - "RequiredPermissionName": "App.Home", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.About", - "DisplayName": "App.About", - "Order": 1, - "Url": "/admin/public/about/designer", - "Icon": "FcAbout", - "RequiredPermissionName": "App.About", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Services", - "DisplayName": "App.Services", - "Order": 2, - "Url": "/admin/public/services/designer", - "Icon": "FcServices", - "RequiredPermissionName": "App.Services", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Orders.Products", - "DisplayName": "App.Orders.Products", - "Order": 3, - "Url": "/admin/list/App.Orders.Products", - "Icon": "FcDiploma1", - "RequiredPermissionName": "App.Orders.Products", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Orders.PaymentMethods", - "DisplayName": "App.Orders.PaymentMethods", - "Order": 4, - "Url": "/admin/list/App.Orders.PaymentMethods", - "Icon": "FcFeedIn", - "RequiredPermissionName": "App.Orders.PaymentMethods", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Orders.InstallmentOptions", - "DisplayName": "App.Orders.InstallmentOptions", - "Order": 5, - "Url": "/admin/list/App.Orders.InstallmentOptions", - "Icon": "FcProcess", - "RequiredPermissionName": "App.Orders.InstallmentOptions", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Orders.SalesOrders", - "DisplayName": "App.Orders.SalesOrders", - "Order": 6, - "Url": "/admin/list/App.Orders.SalesOrders", - "Icon": "FcCollect", - "RequiredPermissionName": "App.Orders.SalesOrders", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.BlogManagement.Category", - "DisplayName": "App.BlogManagement.Category", - "Order": 7, - "Url": "/admin/list/App.BlogManagement.Category", - "Icon": "FaCertificate", - "RequiredPermissionName": "App.BlogManagement.Category", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.BlogManagement.Posts", - "DisplayName": "App.BlogManagement.Posts", - "Order": 8, - "Url": "/admin/list/App.BlogManagement.Posts", - "Icon": "FaWeixin", - "RequiredPermissionName": "App.BlogManagement.Posts", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Demos", - "DisplayName": "App.Demos", - "Order": 9, - "Url": "/admin/list/App.Demos", - "Icon": "FcMissedCall", - "RequiredPermissionName": "App.Demos", - "IsDisabled": false - }, - { - "ParentCode": "App.Public", - "Code": "App.Contact", - "DisplayName": "App.Contact", - "Order": 10, - "Url": "/admin/public/contact/designer", - "Icon": "FcContacts", - "RequiredPermissionName": "App.Contact", - "IsDisabled": false - }, - { "ParentCode": "App.Saas", "Code": "App.Saas.Definitions", "DisplayName": "App.Definitions", - "Order": 2, + "Order": 1, "Url": null, "Icon": "FcFilingCabinet", "RequiredPermissionName": null, @@ -750,7 +629,126 @@ "RequiredPermissionName": "App.Definitions.Sequence", "IsDisabled": false }, - + { + "ParentCode": "App.Saas", + "Code": "App.Public", + "DisplayName": "App.Public", + "Order": 2, + "Url": null, + "Icon": "FcTemplate", + "RequiredPermissionName": null, + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Home", + "DisplayName": "App.Home", + "Order": 0, + "Url": "/admin/public/home/designer", + "Icon": "FcHome", + "RequiredPermissionName": "App.Home", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.About", + "DisplayName": "App.About", + "Order": 1, + "Url": "/admin/public/about/designer", + "Icon": "FcAbout", + "RequiredPermissionName": "App.About", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Services", + "DisplayName": "App.Services", + "Order": 2, + "Url": "/admin/public/services/designer", + "Icon": "FcServices", + "RequiredPermissionName": "App.Services", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Orders.Products", + "DisplayName": "App.Orders.Products", + "Order": 3, + "Url": "/admin/list/App.Orders.Products", + "Icon": "FcDiploma1", + "RequiredPermissionName": "App.Orders.Products", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Orders.PaymentMethods", + "DisplayName": "App.Orders.PaymentMethods", + "Order": 4, + "Url": "/admin/list/App.Orders.PaymentMethods", + "Icon": "FcFeedIn", + "RequiredPermissionName": "App.Orders.PaymentMethods", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Orders.InstallmentOptions", + "DisplayName": "App.Orders.InstallmentOptions", + "Order": 5, + "Url": "/admin/list/App.Orders.InstallmentOptions", + "Icon": "FcProcess", + "RequiredPermissionName": "App.Orders.InstallmentOptions", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Orders.SalesOrders", + "DisplayName": "App.Orders.SalesOrders", + "Order": 6, + "Url": "/admin/list/App.Orders.SalesOrders", + "Icon": "FcCollect", + "RequiredPermissionName": "App.Orders.SalesOrders", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.BlogManagement.Category", + "DisplayName": "App.BlogManagement.Category", + "Order": 7, + "Url": "/admin/list/App.BlogManagement.Category", + "Icon": "FaCertificate", + "RequiredPermissionName": "App.BlogManagement.Category", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.BlogManagement.Posts", + "DisplayName": "App.BlogManagement.Posts", + "Order": 8, + "Url": "/admin/list/App.BlogManagement.Posts", + "Icon": "FaWeixin", + "RequiredPermissionName": "App.BlogManagement.Posts", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Demos", + "DisplayName": "App.Demos", + "Order": 9, + "Url": "/admin/list/App.Demos", + "Icon": "FcMissedCall", + "RequiredPermissionName": "App.Demos", + "IsDisabled": false + }, + { + "ParentCode": "App.Public", + "Code": "App.Contact", + "DisplayName": "App.Contact", + "Order": 10, + "Url": "/admin/public/contact/designer", + "Icon": "FcContacts", + "RequiredPermissionName": "App.Contact", + "IsDisabled": false + }, { "ParentCode": "App.Saas", "Code": "AbpTenantManagement.Tenants", @@ -1043,21 +1041,11 @@ "IsDisabled": false, "ShortName": "Adm" }, - { - "ParentCode": "App.Administration", - "Code": "App.Setting", - "DisplayName": "App.Setting", - "Order": 1, - "Url": "/admin/settings", - "Icon": "FcSettings", - "RequiredPermissionName": "App.Setting", - "IsDisabled": false - }, { "ParentCode": "App.Administration", "Code": "App.Administration.Definitions", "DisplayName": "App.Definitions", - "Order": 2, + "Order": 1, "Url": null, "Icon": "FcFilingCabinet", "RequiredPermissionName": null, @@ -1103,6 +1091,16 @@ "RequiredPermissionName": "App.Definitions.OrgChart", "IsDisabled": false }, + { + "ParentCode": "App.Administration", + "Code": "App.Setting", + "DisplayName": "App.Setting", + "Order": 2, + "Url": "/admin/settings", + "Icon": "FcSettings", + "RequiredPermissionName": "App.Setting", + "IsDisabled": false + }, { "ParentCode": "App.Administration", "Code": "App.Administration.Intranet", diff --git a/api/test/Sozsoft.Platform.EntityFrameworkCore.Tests/Sozsoft.Platform.EntityFrameworkCore.Tests.csproj b/api/test/Sozsoft.Platform.EntityFrameworkCore.Tests/Sozsoft.Platform.EntityFrameworkCore.Tests.csproj index efc9167..b166cca 100644 --- a/api/test/Sozsoft.Platform.EntityFrameworkCore.Tests/Sozsoft.Platform.EntityFrameworkCore.Tests.csproj +++ b/api/test/Sozsoft.Platform.EntityFrameworkCore.Tests/Sozsoft.Platform.EntityFrameworkCore.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/ui/package-lock.json b/ui/package-lock.json index e04e29f..a7d99a5 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -90,7 +90,7 @@ "postcss": "^8.4.21", "prettier": "^3.1.1", "tailwindcss": "^3.4.17", - "typescript": "^4.9.3", + "typescript": "5.9", "vite": "^7.3.6", "vite-plugin-pwa": "^1.3.0" } @@ -3859,6 +3859,189 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.62.1.tgz", + "integrity": "sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/utils": "8.62.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", + "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.62.1", + "@typescript-eslint/tsconfig-utils": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", + "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.62.1", + "@typescript-eslint/types": "^8.62.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", + "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.62.1.tgz", + "integrity": "sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", + "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.62.1", + "@typescript-eslint/tsconfig-utils": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", + "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.62.1", + "@typescript-eslint/types": "^8.62.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", + "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/parser": { "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.1.tgz", @@ -3884,7 +4067,35 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/project-service": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", + "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.62.1", + "@typescript-eslint/tsconfig-utils": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", @@ -3906,6 +4117,23 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", + "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.62.1.tgz", @@ -3924,48 +4152,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.62.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", - "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.62.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.62.1.tgz", - "integrity": "sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.62.1", - "@typescript-eslint/typescript-estree": "8.62.1", - "@typescript-eslint/utils": "8.62.1", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, "node_modules/@typescript-eslint/types": { "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.1.tgz", @@ -3980,58 +4166,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.62.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", - "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.62.1", - "@typescript-eslint/tsconfig-utils": "8.62.1", - "@typescript-eslint/types": "8.62.1", - "@typescript-eslint/visitor-keys": "8.62.1", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.62.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.62.1.tgz", - "integrity": "sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.62.1", - "@typescript-eslint/types": "8.62.1", - "@typescript-eslint/typescript-estree": "8.62.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.1.tgz", @@ -12756,9 +12890,9 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -12766,7 +12900,7 @@ "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { diff --git a/ui/package.json b/ui/package.json index 2f30dbe..8adf4fd 100644 --- a/ui/package.json +++ b/ui/package.json @@ -39,10 +39,10 @@ "dayjs": "^1.11.13", "devexpress-reporting-react": "^25.2.3", "devextreme": "^25.2.3", + "devextreme-exceljs-fork": "^4.4.11", "devextreme-react": "^25.2.3", "easy-peasy": "^6.0.5", "emoji-picker-react": "^4.14.1", - "devextreme-exceljs-fork": "^4.4.11", "file-saver": "^2.0.2", "formik": "^2.4.6", "framer-motion": "^11.15.0", @@ -65,6 +65,7 @@ "yup": "^1.6.1" }, "devDependencies": { + "@eslint/js": "^9.39.0", "@tailwindcss/typography": "^0.5.15", "@types/babel__standalone": "^7.1.9", "@types/file-saver": "^2.0.7", @@ -75,7 +76,6 @@ "@types/react-helmet": "^6.1.9", "@types/react-highlight-words": "^0.16.4", "@types/react-modal": "^3.13.1", - "@eslint/js": "^9.39.0", "@typescript-eslint/eslint-plugin": "^8.62.1", "@typescript-eslint/parser": "^8.62.1", "@vitejs/plugin-react": "^4.2.1", @@ -98,7 +98,7 @@ "postcss": "^8.4.21", "prettier": "^3.1.1", "tailwindcss": "^3.4.17", - "typescript": "^4.9.3", + "typescript": "5.9", "vite": "^7.3.6", "vite-plugin-pwa": "^1.3.0" }, diff --git a/ui/src/components/common/Widget.tsx b/ui/src/components/common/Widget.tsx index 3132e7d..6493e92 100644 --- a/ui/src/components/common/Widget.tsx +++ b/ui/src/components/common/Widget.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; import classNames from "classnames"; -import { iconList } from "./iconList"; +import { iconList } from "../../utils/iconList"; export type colorType = | "blue" diff --git a/ui/src/components/importManager/ImportDashboard.tsx b/ui/src/components/importManager/ImportDashboard.tsx index a3cef8c..bac3110 100644 --- a/ui/src/components/importManager/ImportDashboard.tsx +++ b/ui/src/components/importManager/ImportDashboard.tsx @@ -213,7 +213,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) => const getSessionStatusLabel = (status: string) => { switch (status) { case 'uploading': - return translate('::App.Listforms.ImportManager.Uploading') + return translate('::App.Uploading') case 'validating': return translate('::App.Listforms.ImportManager.Validating') case 'processing': diff --git a/ui/src/components/orders/Cart.tsx b/ui/src/components/orders/Basket.tsx similarity index 86% rename from ui/src/components/orders/Cart.tsx rename to ui/src/components/orders/Basket.tsx index a713ce8..b13d77a 100644 --- a/ui/src/components/orders/Cart.tsx +++ b/ui/src/components/orders/Basket.tsx @@ -4,7 +4,7 @@ import { BillingCycle, BasketItem } from '@/proxy/order/models' import { useLocalization } from '@/utils/hooks/useLocalization' import { Button } from '@/components/ui' -interface CartState { +interface BasketData { items: BasketItem[] subtotal: number vatTotal: number @@ -13,30 +13,30 @@ interface CartState { globalPeriod: number } -interface CartProps { +interface BasketProps { isOpen: boolean onClose: () => void onCheckout: () => void - cartState: CartState + basketData: BasketData updateQuantity: (id: string, quantity: number) => void removeItem: (id: string) => void - clearCart: () => void + clearBasket: () => void } -export const Cart: React.FC = ({ +export const Basket: React.FC = ({ isOpen, onClose, onCheckout, - cartState, + basketData, updateQuantity, removeItem, - clearCart, + clearBasket, }) => { const { translate } = useLocalization() - const handleClearCart = () => { + const handleClearBasket = () => { if (window.confirm('Sepetteki tüm ürünleri silmek istediğinizden emin misiniz?')) { - clearCart() + clearBasket() } } @@ -58,17 +58,17 @@ export const Cart: React.FC = ({

- {translate('::Public.cart.title')} + {translate('::Public.basket.title')}

- {cartState.items.length > 0 && ( + {basketData.items.length > 0 && (
- {cartState.items.length === 0 ? ( + {basketData.items.length === 0 ? (
-

{translate('::Public.cart.empty.title')}

-

{translate('::Public.cart.empty.subtitle')}

+

{translate('::Public.basket.empty.title')}

+

{translate('::Public.basket.empty.subtitle')}

) : (
- {cartState.items.map((item: BasketItem, index: number) => ( + {basketData.items.map((item: BasketItem, index: number) => (
= ({ : item.billingCycle === 'yearly' ? translate('::Public.products.billingcycle.yearly') : translate('::Public.products.billingcycle.monthly')} - {cartState.globalPeriod > 1 && item.product.isQuantityBased && ( + {basketData.globalPeriod > 1 && item.product.isQuantityBased && ( - ({cartState.globalPeriod}{' '} + ({basketData.globalPeriod}{' '} {item.billingCycle === 'monthly' ? translate('::Public.products.billingcycle.month') : translate('::Public.products.billingcycle.year')} @@ -161,29 +161,29 @@ export const Cart: React.FC = ({ )}
- {cartState.items.length > 0 && ( + {basketData.items.length > 0 && (
{translate('::App.Listform.ListformField.Subtotal')} - {formatPrice(cartState.subtotal)} + {formatPrice(basketData.subtotal)}
{translate('::Public.products.kdv')} - {formatPrice(cartState.vatTotal)} + {formatPrice(basketData.vatTotal)}
{translate('::App.Listform.ListformField.Total')} - {formatPrice(cartState.total)} + {formatPrice(basketData.total)}
)} diff --git a/ui/src/components/orders/BillingControls.tsx b/ui/src/components/orders/BillingControls.tsx index 738c08f..2e5552a 100644 --- a/ui/src/components/orders/BillingControls.tsx +++ b/ui/src/components/orders/BillingControls.tsx @@ -1,7 +1,7 @@ import React from 'react' import { FaCalendar, FaClock, FaMinus, FaPlus, FaShoppingCart } from 'react-icons/fa' import { BillingCycle } from '@/proxy/order/models' -import { CartState } from '@/utils/cartUtils' +import { BasketData } from '@/utils/basketUtils' import { useScroll } from '@/contexts/ScrollContext' import { useLocalization } from '@/utils/hooks/useLocalization' import { Button } from '@/components/ui' @@ -11,10 +11,10 @@ interface BillingControlsProps { globalPeriod: number setGlobalBillingCycle: (cycle: BillingCycle) => void setGlobalPeriod: (period: number) => void - onCartClick: () => void + onBasketClick: () => void onNavigate: (section: string) => void - cartItemsCount: number - cartState: CartState + basketItemsCount: number + basketData: BasketData } export const BillingControls: React.FC = ({ @@ -22,11 +22,11 @@ export const BillingControls: React.FC = ({ globalPeriod, setGlobalBillingCycle, setGlobalPeriod, - onCartClick, - cartItemsCount, - cartState, + onBasketClick, + basketItemsCount, + basketData, }) => { - const hasCartItems = cartState.items.length > 0 + const hasBasketItems = basketData.items.length > 0 const isScrolled = useScroll() const { translate } = useLocalization() @@ -48,25 +48,25 @@ export const BillingControls: React.FC = ({
diff --git a/ui/src/components/orders/PaymentForm.tsx b/ui/src/components/orders/PaymentForm.tsx index 1ec60d8..9204125 100644 --- a/ui/src/components/orders/PaymentForm.tsx +++ b/ui/src/components/orders/PaymentForm.tsx @@ -11,7 +11,7 @@ import { CustomTenantDto } from '@/proxy/config/models' import { useLocalization } from '@/utils/hooks/useLocalization' import { Button } from '@/components/ui' -interface CartState { +interface BasketData { items: BasketItem[] subtotal: number vatTotal: number @@ -24,10 +24,10 @@ interface PaymentFormProps { tenant: CustomTenantDto onBack: () => void onComplete: (paymentData: Record) => void - cartState: CartState + basketData: BasketData } -export const PaymentForm: React.FC = ({ onBack, onComplete, cartState }) => { +export const PaymentForm: React.FC = ({ onBack, onComplete, basketData }) => { const defaultPaymentMethod = 'Kredi Kartı' const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(defaultPaymentMethod) const [selectedInstallment, setSelectedInstallment] = useState() @@ -72,14 +72,14 @@ export const PaymentForm: React.FC = ({ onBack, onComplete, ca let commission = 0 if (selectedPaymentMethod === defaultPaymentMethod && selectedInstallment) { - commission = cartState.total * selectedInstallment.commission + commission = basketData.total * selectedInstallment.commission } else if (selectedMethod) { - commission = cartState.total * selectedMethod.commission + commission = basketData.total * selectedMethod.commission } - const finalTotal = cartState.total + commission - const period = cartState.globalPeriod > 0 ? cartState.globalPeriod : 1 - const billingCycle = cartState.globalBillingCycle || 'yearly' + const finalTotal = basketData.total + commission + const period = basketData.globalPeriod > 0 ? basketData.globalPeriod : 1 + const billingCycle = basketData.globalBillingCycle || 'yearly' const licenseEndTime = calculateLicenseEndTime(new Date(licenseStartTime), billingCycle, period) const formatPrice = (price: number) => @@ -91,7 +91,7 @@ export const PaymentForm: React.FC = ({ onBack, onComplete, ca const vatRateLabel = (() => { const rates = Array.from( - new Set(cartState.items.map((item) => Math.round((item.vatRate ?? 0) * 100))), + new Set(basketData.items.map((item) => Math.round((item.vatRate ?? 0) * 100))), ).filter((rate) => rate > 0) return rates.length > 0 ? ` (${rates.map((rate) => `%${rate}`).join(', ')})` : '' @@ -290,7 +290,7 @@ export const PaymentForm: React.FC = ({ onBack, onComplete, ca
{formatPrice( - (cartState.total + cartState.total * option.commission) / + (basketData.total + basketData.total * option.commission) / option.installment, )}
@@ -356,7 +356,7 @@ export const PaymentForm: React.FC = ({ onBack, onComplete, ca
- {cartState.items.map((item, index) => ( + {basketData.items.map((item, index) => (
@@ -387,11 +387,11 @@ export const PaymentForm: React.FC = ({ onBack, onComplete, ca
{translate('::Public.payment.summary.subtotal')} - {formatPrice(cartState.subtotal)} + {formatPrice(basketData.subtotal)}
{translate('::Public.products.kdv')}{vatRateLabel} - {formatPrice(cartState.vatTotal)} + {formatPrice(basketData.vatTotal)}
{translate('::Public.payment.installments.commission')} diff --git a/ui/src/components/orders/ProductCard.tsx b/ui/src/components/orders/ProductCard.tsx index 8b4e9c5..8f6d280 100644 --- a/ui/src/components/orders/ProductCard.tsx +++ b/ui/src/components/orders/ProductCard.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import { FaPlus, FaMinus } from 'react-icons/fa' import { BillingCycle, ProductDto } from '@/proxy/order/models' -import { CartState } from '@/utils/cartUtils' +import { BasketData } from '@/utils/basketUtils' import { useLocalization } from '@/utils/hooks/useLocalization' import { Button } from '@/components/ui' @@ -10,7 +10,7 @@ interface ProductCardProps { globalBillingCycle: BillingCycle globalPeriod: number addItem: (product: ProductDto, quantity: number, billingCycle: BillingCycle) => void - cartState: CartState + basketData: BasketData } export const ProductCard: React.FC = ({ @@ -18,13 +18,12 @@ export const ProductCard: React.FC = ({ globalBillingCycle, globalPeriod, addItem, - cartState, + basketData, }) => { const [quantity, setQuantity] = useState(1) const { translate } = useLocalization() - // Direct check with current cart state - const isInCart = cartState.items.some( + const isInBasket = basketData.items.some( (item) => item.product.id === product.id && item.billingCycle === globalBillingCycle, ) @@ -54,13 +53,11 @@ export const ProductCard: React.FC = ({ return getTotalPrice() + getVatAmount() } - const handleAddToCart = () => { - // Non-quantity products should not be added if already in cart - if (!product.isQuantityBased && isInCart) { + const handleAddToBasket = () => { + if (!product.isQuantityBased && isInBasket) { return } - // For non-quantity products, always use quantity 1 const quantityToAdd = !product.isQuantityBased ? 1 : quantity addItem(product, quantityToAdd, globalBillingCycle) setQuantity(1) @@ -180,18 +177,18 @@ export const ProductCard: React.FC = ({ {(() => { const isNonQuantityProduct = !product.isQuantityBased - const isDisabled = isNonQuantityProduct && isInCart + const isDisabled = isNonQuantityProduct && isInBasket return ( ) })()} diff --git a/ui/src/components/orders/ProductCatalog.tsx b/ui/src/components/orders/ProductCatalog.tsx index 5518a72..097debb 100644 --- a/ui/src/components/orders/ProductCatalog.tsx +++ b/ui/src/components/orders/ProductCatalog.tsx @@ -1,7 +1,7 @@ import React, { useState, useMemo, useEffect } from 'react' import { FaFilter, FaSearch } from 'react-icons/fa' import { ProductCard } from './ProductCard' -import { addItemToCart, CartState } from '@/utils/cartUtils' +import { addItemToBasket, BasketData } from '@/utils/basketUtils' import { BillingCycle, ProductDto } from '@/proxy/order/models' import { OrderService } from '@/services/order.service' import { useLocalization } from '@/utils/hooks/useLocalization' @@ -11,15 +11,15 @@ import { Button } from '@/components/ui' interface ProductCatalogProps { searchQuery: string onSearchChange: (query: string) => void - cartState: CartState - setCartState: React.Dispatch> + basketData: BasketData + setBasketData: React.Dispatch> } export const ProductCatalog: React.FC = ({ searchQuery, onSearchChange, - cartState, - setCartState, + basketData, + setBasketData, }) => { const { translate } = useLocalization() @@ -45,24 +45,24 @@ export const ProductCatalog: React.FC = ({ }, []) const handleAddItem = (product: ProductDto, quantity: number, billingCycle: BillingCycle) => { - setCartState((currentState) => addItemToCart(currentState, product, quantity, billingCycle)) + setBasketData((currentState) => addItemToBasket(currentState, product, quantity, billingCycle)) } const availableProducts = useMemo(() => { return products.filter((product) => { // If monthly billing is selected, only show products with monthlyPrice - if (cartState.globalBillingCycle === 'monthly') { + if (basketData.globalBillingCycle === 'monthly') { return product.monthlyPrice !== undefined } // If yearly billing is selected, only show products with yearlyPrice - if (cartState.globalBillingCycle === 'yearly') { + if (basketData.globalBillingCycle === 'yearly') { return product.yearlyPrice !== undefined } return true }) - }, [products, cartState.globalBillingCycle]) + }, [products, basketData.globalBillingCycle]) const categories = useMemo(() => { const cats = ['all', ...new Set(availableProducts.map((p) => p.category))] @@ -161,10 +161,10 @@ export const ProductCatalog: React.FC = ({ ))}
diff --git a/ui/src/components/orders/TenantForm.tsx b/ui/src/components/orders/TenantForm.tsx index 9e0e649..38e6cfa 100644 --- a/ui/src/components/orders/TenantForm.tsx +++ b/ui/src/components/orders/TenantForm.tsx @@ -40,6 +40,7 @@ interface LocationOption { } const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ +const WEBSITE_PATTERN = /^(https?:\/\/)?(www\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(\/[^\s]*)?$/ const DEFAULT_PHONE_FORMAT = '000 000 000 000 000' const TURKEY_PHONE_FORMAT = '(000) 000-0000' const REQUIRED_NEW_CUSTOMER_FIELDS: Array = [ @@ -185,6 +186,7 @@ export const TenantForm: React.FC = ({ onSubmit }) => { const [isLoadingDistricts, setIsLoadingDistricts] = useState(false) const [isLoadingTenant, setIsLoadingTenant] = useState(false) const [emailError, setEmailError] = useState('') + const [websiteError, setWebsiteError] = useState('') const [phoneError, setPhoneError] = useState('') const [existingTenantError, setExistingTenantError] = useState('') const [formError, setFormError] = useState('') @@ -355,6 +357,11 @@ export const TenantForm: React.FC = ({ onSubmit }) => { hasValidationError = true } + if (!isExisting && !WEBSITE_PATTERN.test(formData.website || '')) { + setWebsiteError('Lütfen geçerli bir web sitesi adresi girin.') + hasValidationError = true + } + if (hasValidationError) return onSubmit({ ...formData, @@ -391,6 +398,7 @@ export const TenantForm: React.FC = ({ onSubmit }) => { setExistingTenantError('') setFormError('') setEmailError('') + setWebsiteError('') setPhoneError('') setDistricts([]) setFormData(nextIsExisting ? {} : getDefaultNewCustomerData()) @@ -963,7 +971,7 @@ export const TenantForm: React.FC = ({ onSubmit }) => { setEmailError( EMAIL_PATTERN.test(e.target.value) ? '' - : 'Lütfen geçerli bir e-posta adresi girin.', + : translate('::App.Email.PatternError'), ) } }} @@ -971,7 +979,7 @@ export const TenantForm: React.FC = ({ onSubmit }) => { setEmailError( EMAIL_PATTERN.test(formData.email || '') ? '' - : 'Lütfen geçerli bir e-posta adresi girin.', + : translate('::App.Email.PatternError'), ) } aria-invalid={Boolean(emailError)} @@ -1001,7 +1009,7 @@ export const TenantForm: React.FC = ({ onSubmit }) => { handleInputChange('taxOffice', e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg bg-white text-gray-900 placeholder-gray-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent" @@ -1038,10 +1046,37 @@ export const TenantForm: React.FC = ({ onSubmit }) => { required placeholder={translate('::Public.payment.customer.website')} value={formData.website || ''} - onChange={(e) => handleInputChange('website', e.target.value)} - className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg bg-white text-gray-900 placeholder-gray-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent" + onChange={(e) => { + handleInputChange('website', e.target.value) + if (websiteError) { + setWebsiteError( + WEBSITE_PATTERN.test(e.target.value) + ? '' + : translate('::App.WebSite.PatternError'), + ) + } + }} + onBlur={() => + setWebsiteError( + WEBSITE_PATTERN.test(formData.website || '') + ? '' + : translate('::App.WebSite.PatternError'), + ) + } + aria-invalid={Boolean(websiteError)} + aria-describedby={websiteError ? 'tenant-website-error' : undefined} + className={`w-full pl-10 pr-4 py-2 border rounded-lg bg-white text-gray-900 placeholder-gray-500 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent ${ + websiteError + ? 'border-red-500 dark:border-red-500' + : 'border-gray-300 dark:border-gray-700' + }`} />
+ {websiteError && ( +

+ {websiteError} +

+ )}