Created
September 23, 2025 20:51
-
-
Save jay-babu/2888ec0e72b82c500a1dc2b9cf170314 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/.claude/settings.local.json b/.claude/settings.local.json | |
| index 4592182d..9f305e06 100644 | |
| --- a/.claude/settings.local.json | |
| +++ b/.claude/settings.local.json | |
| @@ -1,8 +1,7 @@ | |
| { | |
| "permissions": { | |
| "allow": [ | |
| - "Bash(grep:*)", | |
| - "Bash(npm test:*)" | |
| + "Bash(grep:*)" | |
| ], | |
| "deny": [] | |
| }, | |
| diff --git a/.env.development b/.env.development | |
| index 7fb2fe6d..3eaacafb 100644 | |
| --- a/.env.development | |
| +++ b/.env.development | |
| @@ -1,6 +1,4 @@ | |
| -VITE_APP_API_URL=http://localhost:8080 | |
| -# VITE_APP_API_URL=https://dev.api.transformity.tech | |
| -# VITE_APP_API_URL=https://api.transformity.tech | |
| +VITE_APP_API_URL=http://localhost:8080 # https://dev.api.transformity.tech | |
| VITE_APP_PUBLIC_POSTHOG_KEY=phc_sr0PGw2BOIuoyKjJy3I7Jp4I9WCxXjEs3d1JbZJIJy4 | |
| VITE_APP_PUBLIC_POSTHOG_HOST=https://djyhwry6chcok.cloudfront.net | |
| VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51RLs6OD7Vv3KEo8tiRoLtYecfpUdYGbjpV8O1StUCrSLlHLj8FG67wzbJo0r9JAd30EbPlN3ubmVsl0ZwrP6mxVt0004CL9PvY | |
| @@ -10,7 +8,3 @@ VITE_APP_QUILL_COHORT_PUBLIC_KEY=66e9b50d131e7b000bd5fadf | |
| VITE_APP_QUILL_ENTITY_PUBLIC_KEY=66e9b50d131e7b000bd5fadf | |
| VITE_APP_PAYRIX_PUBLIC_KEY=2e43da0fa5560fe20d8d386e7b9fd155 | |
| VITE_APP_PAYRIX_URL=https://test-api.payrix.com | |
| -VITE_APP_ZEUS_URL=https://zeus.usemargin.dev | |
| -# VITE_APP_ZEUS_URL=http://localhost:9090 | |
| -VITE_APP_PHOENIX_URL=https://d338aujdgql5cv.cloudfront.net | |
| -VITE_APP_PUBLIC_STATSIG_CLIENT_KEY=client-eRuybgghH4DCiONufndDbCFW3LDLxnLg1hU38YbAI55 | |
| diff --git a/.env.production b/.env.production | |
| index 5fabf3e6..c723ef8b 100644 | |
| --- a/.env.production | |
| +++ b/.env.production | |
| @@ -6,4 +6,3 @@ VITE_APP_QUILL_COHORT_PUBLIC_KEY=66e9c30e131e7b000bd62af7 | |
| VITE_APP_QUILL_ENTITY_PUBLIC_KEY=66ff8a2cedc87e000be77866 | |
| VITE_APP_PAYRIX_PUBLIC_KEY=4804148321779a32edc8948702233442 | |
| VITE_APP_PAYRIX_URL=https://api.payrix.com | |
| -VITE_APP_PUBLIC_STATSIG_CLIENT_KEY=client-eRuybgghH4DCiONufndDbCFW3LDLxnLg1hU38YbAI55 | |
| diff --git a/.prettierrc.json b/.prettierrc.json | |
| index fc362149..55c1943a 100644 | |
| --- a/.prettierrc.json | |
| +++ b/.prettierrc.json | |
| @@ -1,3 +1,3 @@ | |
| { | |
| - "plugins": ["@prettier/plugin-oxc", "prettier-plugin-organize-imports"] | |
| + "plugins": ["prettier-plugin-organize-imports"] | |
| } | |
| diff --git a/CRUSH.md b/CRUSH.md | |
| index a8e45596..8e0bbf1e 100644 | |
| --- a/CRUSH.md | |
| +++ b/CRUSH.md | |
| @@ -34,16 +34,6 @@ | |
| **Hardware:** Receipt printing via WebSerial/WebUSB APIs. Barcode scanning via webhid-barcode-scanner. | |
| -## UX/Design Principles | |
| - | |
| -**Smooth Transitions:** Prioritize polished user experiences with CSS transitions over abrupt state changes. Prevent UI jitters with morphing containers and adaptive layouts. | |
| - | |
| -**Information Preservation:** Keep users informed during loading states - show current data with loading indicators rather than hiding content. | |
| - | |
| -**Professional POS Standards:** Solutions must feel enterprise-grade for retail/hospitality. Maintain existing design systems while improving behavior. | |
| - | |
| -**Problem-Solving Process:** Use v0 for brainstorming multiple approaches with pros/cons before implementing. Consider real-world POS usage scenarios. | |
| - | |
| ## Cursor Rules Integration | |
| Follow `.cursor/rules/core.mdc` principles: verify before changing, use workspace-relative paths for edits, prioritize reusability. | |
| diff --git a/POSServiceModel b/POSServiceModel | |
| index d732267c..1d26bce3 160000 | |
| --- a/POSServiceModel | |
| +++ b/POSServiceModel | |
| @@ -1 +1 @@ | |
| -Subproject commit d732267c11242488a61ec7697e50151c7a2aa438 | |
| +Subproject commit 1d26bce3aa66370e48b8d816d73b889a2086f4c4 | |
| diff --git a/Pulumi.beta.yaml b/Pulumi.beta.yaml | |
| index 23a5500b..554dc411 100644 | |
| --- a/Pulumi.beta.yaml | |
| +++ b/Pulumi.beta.yaml | |
| @@ -1,5 +1,2 @@ | |
| -config: | |
| - aws:region: us-east-1 | |
| - domain: pos.beta.transformity.tech | |
| secretsprovider: awskms://alias/pulumi-production?region=us-east-1 | |
| encryptedkey: AQICAHgW5CflR2+hwkIP9fktbEu4lWc/+eDpIVQFzsK4gQ/4jAGoJHcy7wgufaEUWYywsrSeAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM4apEm63r8/TEc58fAgEQgDu0BYl0Ds4IihI3ETcRMSI1kBZ2jQk/vplRt1NLV/mxJGbqAJYbWZ3qcXuwrQJ8ua+VBj0W5SQIP+ZRdg== | |
| diff --git a/Pulumi.gamma.yaml b/Pulumi.gamma.yaml | |
| index 7bd23ffa..17cd80dc 100644 | |
| --- a/Pulumi.gamma.yaml | |
| +++ b/Pulumi.gamma.yaml | |
| @@ -1,5 +1,4 @@ | |
| config: | |
| aws:region: us-east-1 | |
| - domain: dev.pos.transformity.tech | |
| secretsprovider: awskms://alias/pulumi-gamma?region=us-east-1 | |
| encryptedkey: AQICAHhl5kPDyg+7mJXABM7RtmPC6Q7j6ZQpqxejHGBgEvasxAG1SalUPbQ5aGcDJa3bVqu3AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMvmetfZzSFmVgupY8AgEQgDtypZUSSpk1naBdUmOFfIpJp/Ebm19ZBc1xfucZ11DYF8aZLJVYzX59o+2G18QiVHFO1b/kdbkrqweg3A== | |
| diff --git a/Pulumi.prod.yaml b/Pulumi.prod.yaml | |
| index c5482b69..00edbc7a 100644 | |
| --- a/Pulumi.prod.yaml | |
| +++ b/Pulumi.prod.yaml | |
| @@ -1,5 +1,2 @@ | |
| -config: | |
| - aws:region: us-east-1 | |
| - domain: pos.transformity.tech | |
| secretsprovider: awskms://alias/pulumi-production?region=us-east-1 | |
| encryptedkey: AQICAHgW5CflR2+hwkIP9fktbEu4lWc/+eDpIVQFzsK4gQ/4jAEO0WS/feDuFf6S5LCVMJcnAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMmoxu0ii2FiXr9Mm9AgEQgDvVTrrashM0MSWHYOlpgoY3jOUHAiBHD54lP7PZHfRGYTT0Ge+tJhyhUyLd/FxeJbjVDonIvS1YR3bz9A== | |
| diff --git a/eslint.config.mjs b/eslint.config.mjs | |
| index 31fe81ad..ef1e7ad2 100644 | |
| --- a/eslint.config.mjs | |
| +++ b/eslint.config.mjs | |
| @@ -55,7 +55,6 @@ export default defineConfig([ | |
| }, | |
| rules: { | |
| "@typescript-eslint/no-floating-promises": "error", | |
| - "react-hooks/exhaustive-deps": "error", | |
| }, | |
| }, | |
| ]); | |
| diff --git a/index.ts b/index.ts | |
| index 6d6bc6c5..5f863480 100644 | |
| --- a/index.ts | |
| +++ b/index.ts | |
| @@ -5,51 +5,22 @@ import * as fs from "fs"; | |
| import * as path from "path"; | |
| import { cwd } from "process"; | |
| +const org = pulumi.getOrganization(); | |
| const stack = pulumi.getStack(); | |
| -const config = new pulumi.Config(); | |
| + | |
| +const backendStack = new pulumi.StackReference( | |
| + `${org}/pos-backend/${stack === "prod" ? "production" : stack}`, | |
| +); | |
| +const wildcardCertificate = backendStack | |
| + .getOutput("wildcardCertificate") | |
| + .apply((cert: aws.acm.Certificate) => cert); | |
| + | |
| const getBranches = ( | |
| stack: string, | |
| appId: Output<string>, | |
| ): { branch: aws.amplify.Branch; name: string }[] => { | |
| switch (stack) { | |
| case "beta": | |
| - return [ | |
| - { | |
| - branch: new aws.amplify.Branch( | |
| - "pos-frontend-amplify-branch-prod", | |
| - { | |
| - appId: appId, | |
| - branchName: "release", | |
| - displayName: "release", | |
| - framework: "React", | |
| - region: "us-east-1", | |
| - stage: "PRODUCTION", | |
| - ttl: "5", | |
| - }, | |
| - { | |
| - protect: true, | |
| - }, | |
| - ), | |
| - name: "CANARY", | |
| - }, | |
| - { | |
| - branch: new aws.amplify.Branch( | |
| - "pos-frontend-amplify-branch-beta", | |
| - { | |
| - appId: appId, | |
| - branchName: "beta", | |
| - displayName: "beta", | |
| - region: "us-east-1", | |
| - stage: "BETA", | |
| - ttl: "5", | |
| - }, | |
| - { | |
| - protect: true, | |
| - }, | |
| - ), | |
| - name: "STABLE", | |
| - }, | |
| - ]; | |
| case "prod": | |
| return [ | |
| { | |
| @@ -84,14 +55,14 @@ const getBranches = ( | |
| "https://beta.sale.api.transformity.tech", | |
| }, | |
| region: "us-east-1", | |
| - stage: "BETA", | |
| + stage: "NONE", | |
| ttl: "5", | |
| }, | |
| { | |
| protect: true, | |
| }, | |
| ), | |
| - name: "CANARY", | |
| + name: "BETA", | |
| }, | |
| ]; | |
| case "gamma": | |
| @@ -120,7 +91,7 @@ const getBranches = ( | |
| stage: "PRODUCTION", | |
| ttl: "5", | |
| }), | |
| - name: "CANARY", | |
| + name: "BETA", | |
| }, | |
| ]; | |
| default: | |
| @@ -201,7 +172,7 @@ const getAmplify = (stack: string) => { | |
| jobConfig: { | |
| buildComputeType: "LARGE_16GB", | |
| }, | |
| - name: `TransformityPOSFrontend-${stack}`, | |
| + name: "TransformityPOSFrontend", | |
| platform: "WEB", | |
| region: "us-east-1", | |
| repository: "https://github.com/Transformity/TransformityPOSFrontend", | |
| @@ -211,91 +182,28 @@ const getAmplify = (stack: string) => { | |
| }, | |
| ); | |
| case "beta": | |
| - return new aws.amplify.App( | |
| - "pos-frontend-amplify-beta", | |
| - { | |
| - buildSpec: `version: 1 | |
| -frontend: | |
| - phases: | |
| - preBuild: | |
| - commands: | |
| - - export NODE_OPTIONS=--max-old-space-size=8192 | |
| - - npm ci --cache .npm --prefer-offline | |
| - build: | |
| - commands: | |
| - - npm run build | |
| - artifacts: | |
| - baseDirectory: build | |
| - files: | |
| - - "**/*" | |
| - paths: | |
| - - .npm/**/* | |
| - - node_modules/**/* | |
| - - node_modules/.vite/**/* | |
| - `, | |
| - cacheConfig: { | |
| - type: "AMPLIFY_MANAGED_NO_COOKIES", | |
| - }, | |
| - customRules: [ | |
| - { | |
| - source: "/<*>", | |
| - status: "404-200", | |
| - target: "/index.html", | |
| - }, | |
| - ], | |
| - environmentVariables: { | |
| - NODE_OPTIONS: "--max_old_space_size=4096", | |
| - SENTRY_AUTH_TOKEN: | |
| - "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", | |
| - VITE_APP_API_URL: "https://beta.production.api.transformity.tech", | |
| - VITE_APP_PHOENIX_URL: "https://d1la6gp2rlyhl5.cloudfront.net", | |
| - VITE_APP_SALE_API_URL: "https://beta.sale.api.transformity.tech", | |
| - VITE_APP_WEBSOCKET_URL: | |
| - "wss://7c0kxkslb9.execute-api.us-east-1.amazonaws.com/$default/", | |
| - VITE_APP_ZEUS_URL: "https://zeus.usemargin.com", | |
| - _LIVE_UPDATES: JSON.stringify([ | |
| - { | |
| - name: "Node.js version", | |
| - pkg: "node", | |
| - type: "nvm", | |
| - version: "20", | |
| - }, | |
| - ]), | |
| - }, | |
| - jobConfig: { | |
| - buildComputeType: "LARGE_16GB", | |
| - }, | |
| - name: `TransformityPOSFrontend-${stack}`, | |
| - platform: "WEB", | |
| - region: "us-east-1", | |
| - repository: "https://github.com/Transformity/TransformityPOSFrontend", | |
| - }, | |
| - { | |
| - protect: true, | |
| - }, | |
| - ); | |
| case "prod": | |
| return new aws.amplify.App( | |
| "pos-frontend-amplify-prod", | |
| { | |
| buildSpec: `version: 1 | |
| -frontend: | |
| - phases: | |
| - preBuild: | |
| - commands: | |
| - - export NODE_OPTIONS=--max-old-space-size=8192 | |
| - - npm ci --cache .npm --prefer-offline | |
| - build: | |
| - commands: | |
| - - npm run build | |
| - artifacts: | |
| - baseDirectory: build | |
| - files: | |
| - - '**/*' | |
| - paths: | |
| - - .npm/**/* | |
| - - node_modules/**/* | |
| - - node_modules/.vite/**/* # Vite | |
| + frontend: | |
| + phases: | |
| + preBuild: | |
| + commands: | |
| + - export NODE_OPTIONS=--max-old-space-size=8192 | |
| + - npm ci --cache .npm --prefer-offline | |
| + build: | |
| + commands: | |
| + - npm run build | |
| + artifacts: | |
| + baseDirectory: build | |
| + files: | |
| + - '**/*' | |
| + paths: | |
| + - .npm/**/* | |
| + - node_modules/**/* | |
| + - node_modules/.vite/**/* # Vite | |
| `, | |
| cacheConfig: { | |
| type: "AMPLIFY_MANAGED", | |
| @@ -335,7 +243,6 @@ frontend: | |
| VITE_APP_SALE_API_URL: "https://api.transformity.tech", | |
| VITE_APP_WEBSOCKET_URL: | |
| "wss://7c0kxkslb9.execute-api.us-east-1.amazonaws.com/$default/", | |
| - VITE_APP_PHOENIX_URL: "https://d1la6gp2rlyhl5.cloudfront.net", | |
| VITE_APP_ZEUS_URL: "https://zeus.usemargin.com", | |
| _LIVE_UPDATES: JSON.stringify([ | |
| { | |
| @@ -349,7 +256,7 @@ frontend: | |
| jobConfig: { | |
| buildComputeType: "LARGE_16GB", | |
| }, | |
| - name: `TransformityPOSFrontend-${stack}`, | |
| + name: "TransformityPOSFrontend", | |
| platform: "WEB", | |
| region: "us-east-1", | |
| repository: "https://github.com/Transformity/TransformityPOSFrontend", | |
| @@ -363,15 +270,6 @@ frontend: | |
| } | |
| }; | |
| -const getCookieStackName = (stack: string) => { | |
| - switch (stack) { | |
| - case "beta": | |
| - return "prod"; | |
| - default: | |
| - return stack; | |
| - } | |
| -}; | |
| - | |
| const amplify = getAmplify(stack); | |
| const branches = getBranches(stack, amplify.id); | |
| @@ -411,16 +309,12 @@ const lambdaEdgePolicy = new aws.iam.RolePolicyAttachment( | |
| }, | |
| ); | |
| -const originRouterCode = fs.readFileSync( | |
| +// Read the Lambda function code | |
| +const lambdaCode = fs.readFileSync( | |
| path.join(cwd(), "lambda-edge/origin-router.js"), | |
| "utf8", | |
| ); | |
| -const originResponseCode = fs.readFileSync( | |
| - path.join(cwd(), "lambda-edge/origin-response.js"), | |
| - "utf8", | |
| -); | |
| - | |
| // Create Lambda@Edge function for origin routing | |
| const originRouterLambda = new aws.lambda.Function( | |
| `origin-router-${stack}`, | |
| @@ -429,7 +323,7 @@ const originRouterLambda = new aws.lambda.Function( | |
| handler: "index.handler", | |
| role: lambdaEdgeRole.arn, | |
| code: new pulumi.asset.AssetArchive({ | |
| - "index.js": new pulumi.asset.StringAsset(originRouterCode), | |
| + "index.js": new pulumi.asset.StringAsset(lambdaCode), | |
| }), | |
| timeout: 5, | |
| memorySize: 128, | |
| @@ -442,324 +336,48 @@ const originRouterLambda = new aws.lambda.Function( | |
| }, | |
| ); | |
| -// Create Lambda@Edge function for origin response | |
| -const originResponseLambda = new aws.lambda.Function( | |
| - `origin-response-${stack}`, | |
| - { | |
| - runtime: "nodejs18.x", | |
| - handler: "index.handler", | |
| - role: lambdaEdgeRole.arn, | |
| - code: new pulumi.asset.AssetArchive({ | |
| - "index.js": new pulumi.asset.StringAsset(originResponseCode), | |
| - }), | |
| - timeout: 5, | |
| - memorySize: 128, | |
| - publish: true, // Required for Lambda@Edge | |
| - // Note: Lambda@Edge cannot have environment variables | |
| - }, | |
| - { | |
| - provider: usEast1Provider, // Must be in us-east-1 for Lambda@Edge | |
| - dependsOn: [lambdaEdgePolicy], | |
| - }, | |
| -); | |
| - | |
| -// Get the qualified ARNs (with version) for Lambda@Edge | |
| -const originRouterVersionArn = pulumi.interpolate`${originRouterLambda.arn}:${originRouterLambda.version}`; | |
| -const originResponseVersionArn = pulumi.interpolate`${originResponseLambda.arn}:${originResponseLambda.version}`; | |
| - | |
| -// Create Response Headers Policy to allow custom headers from Lambda@Edge | |
| -const responseHeadersPolicy = new aws.cloudfront.ResponseHeadersPolicy( | |
| - `pos-frontend-response-headers-${stack}`, | |
| - { | |
| - name: `pos-frontend-response-headers-${stack}`, | |
| - customHeadersConfig: { | |
| - items: [ | |
| - { | |
| - header: "X-Served-From", | |
| - override: false, | |
| - value: "unknown", // This will be overridden by Lambda@Edge | |
| - }, | |
| - { | |
| - header: "X-Origin-Domain", | |
| - override: false, | |
| - value: "unknown", // This will be overridden by Lambda@Edge | |
| - }, | |
| - { | |
| - header: "X-Stack", | |
| - override: false, | |
| - value: "unknown", // This will be overridden by Lambda@Edge | |
| - }, | |
| - ], | |
| - }, | |
| - }, | |
| -); | |
| - | |
| -// Create WAF Web ACL | |
| -const webAcl = new aws.wafv2.WebAcl( | |
| - `pos-frontend-waf-${stack}`, | |
| - { | |
| - name: `pos-frontend-waf-${stack}`, | |
| - description: "WAF ACL for POS Frontend CloudFront distribution", | |
| - scope: "CLOUDFRONT", | |
| - defaultAction: { | |
| - allow: {}, | |
| - }, | |
| - rules: [ | |
| - // Rate limiting rule - 2000 requests per 5-minute window per IP | |
| - { | |
| - name: "RateLimitRule", | |
| - priority: 1, | |
| - action: { | |
| - block: { | |
| - customResponse: { | |
| - responseCode: 429, | |
| - customResponseBodyKey: "rate_limit_body", | |
| - }, | |
| - }, | |
| - }, | |
| - statement: { | |
| - rateBasedStatement: { | |
| - limit: 3000, | |
| - aggregateKeyType: "IP", | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "RateLimitRule", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - // AWS Managed Core Rule Set - protection against OWASP Top 10 | |
| - { | |
| - name: "AWSManagedRulesCommonRuleSet", | |
| - priority: 2, | |
| - overrideAction: { | |
| - none: {}, | |
| - }, | |
| - statement: { | |
| - managedRuleGroupStatement: { | |
| - vendorName: "AWS", | |
| - name: "AWSManagedRulesCommonRuleSet", | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "AWSManagedRulesCommonRuleSetMetric", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - // AWS Managed Known Bad Inputs Rule Set | |
| - { | |
| - name: "AWSManagedRulesKnownBadInputsRuleSet", | |
| - priority: 3, | |
| - overrideAction: { | |
| - none: {}, | |
| - }, | |
| - statement: { | |
| - managedRuleGroupStatement: { | |
| - vendorName: "AWS", | |
| - name: "AWSManagedRulesKnownBadInputsRuleSet", | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "AWSManagedRulesKnownBadInputsRuleSetMetric", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - // AWS Managed Amazon IP Reputation List | |
| - { | |
| - name: "AWSManagedRulesAmazonIpReputationList", | |
| - priority: 4, | |
| - overrideAction: { | |
| - none: {}, | |
| - }, | |
| - statement: { | |
| - managedRuleGroupStatement: { | |
| - vendorName: "AWS", | |
| - name: "AWSManagedRulesAmazonIpReputationList", | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "AWSManagedRulesAmazonIpReputationListMetric", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - // SQL injection protection | |
| - { | |
| - name: "AWSManagedRulesSQLiRuleSet", | |
| - priority: 5, | |
| - overrideAction: { | |
| - none: {}, | |
| - }, | |
| - statement: { | |
| - managedRuleGroupStatement: { | |
| - vendorName: "AWS", | |
| - name: "AWSManagedRulesSQLiRuleSet", | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "AWSManagedRulesSQLiRuleSetMetric", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - // Geographic restriction - Block specific countries if needed | |
| - { | |
| - name: "GeoBlockingRule", | |
| - priority: 6, | |
| - action: { | |
| - block: {}, | |
| - }, | |
| - statement: { | |
| - geoMatchStatement: { | |
| - // Block countries known for high attack rates - customize as needed | |
| - countryCodes: ["CN", "RU", "KP"], // China, Russia, North Korea | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "GeoBlockingRule", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - // Size constraint rule - prevent large payloads | |
| - { | |
| - name: "SizeRestrictionRule", | |
| - priority: 7, | |
| - action: { | |
| - block: {}, | |
| - }, | |
| - statement: { | |
| - orStatement: { | |
| - statements: [ | |
| - { | |
| - sizeConstraintStatement: { | |
| - fieldToMatch: { | |
| - body: { | |
| - oversizeHandling: "MATCH", | |
| - }, | |
| - }, | |
| - comparisonOperator: "GT", | |
| - size: 8192, // 8KB limit for body | |
| - textTransformations: [ | |
| - { | |
| - priority: 0, | |
| - type: "NONE", | |
| - }, | |
| - ], | |
| - }, | |
| - }, | |
| - { | |
| - sizeConstraintStatement: { | |
| - fieldToMatch: { | |
| - singleHeader: { | |
| - name: "content-length", | |
| - }, | |
| - }, | |
| - comparisonOperator: "GT", | |
| - size: 8192, | |
| - textTransformations: [ | |
| - { | |
| - priority: 0, | |
| - type: "NONE", | |
| - }, | |
| - ], | |
| - }, | |
| - }, | |
| - ], | |
| - }, | |
| - }, | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: "SizeRestrictionRule", | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - }, | |
| - ], | |
| - customResponseBodies: [ | |
| - { | |
| - key: "rate_limit_body", | |
| - content: "Too many requests. Please try again later.", | |
| - contentType: "TEXT_PLAIN", | |
| - }, | |
| - ], | |
| - visibilityConfig: { | |
| - cloudwatchMetricsEnabled: true, | |
| - metricName: `pos-frontend-waf-${stack}`, | |
| - sampledRequestsEnabled: true, | |
| - }, | |
| - tags: { | |
| - Name: `pos-frontend-waf-${stack}`, | |
| - Environment: stack, | |
| - }, | |
| - }, | |
| - { | |
| - provider: usEast1Provider, // WAF for CloudFront must be in us-east-1 | |
| - }, | |
| -); | |
| - | |
| -// Use AWS managed policies to disable caching and forward all viewer headers (except Host) | |
| -const cachingDisabledPolicy = aws.cloudfront | |
| - .getCachePolicyOutput({ | |
| - name: "Managed-CachingDisabled", | |
| - }) | |
| - .apply((policy) => { | |
| - if (!policy.id) { | |
| - throw new Error("Failed to get caching disabled policy"); | |
| - } | |
| - return policy.id; | |
| - }); | |
| -const allViewerExceptHostHeaderPolicy = aws.cloudfront | |
| - .getOriginRequestPolicyOutput({ | |
| - name: "Managed-AllViewerExceptHostHeader", | |
| - }) | |
| - .apply((policy) => { | |
| - if (!policy.id) { | |
| - throw new Error("Failed to get all viewer except host header policy"); | |
| - } | |
| - return policy.id; | |
| - }); | |
| - | |
| -const certificate = new aws.acm.Certificate( | |
| - `pos-frontend-certificate-${stack}`, | |
| - { | |
| - domainName: config.require("domain"), | |
| - validationMethod: "DNS", | |
| - }, | |
| -); | |
| +// Get the qualified ARN (with version) for Lambda@Edge | |
| +const lambdaVersionArn = pulumi.interpolate`${originRouterLambda.arn}:${originRouterLambda.version}`; | |
| const distribution = new aws.cloudfront.Distribution( | |
| `pos-frontend-distribution-${stack}`, | |
| { | |
| - webAclId: webAcl.arn, | |
| defaultCacheBehavior: { | |
| - allowedMethods: ["GET", "HEAD", "OPTIONS"], | |
| + allowedMethods: [ | |
| + "DELETE", | |
| + "GET", | |
| + "HEAD", | |
| + "OPTIONS", | |
| + "PATCH", | |
| + "POST", | |
| + "PUT", | |
| + ], | |
| cachedMethods: ["GET", "HEAD"], | |
| compress: true, | |
| // Use default origin as the primary | |
| - targetOriginId: pulumi.interpolate`${branches.find((branch) => branch.name === "STABLE")?.branch.branchName}.${amplify.defaultDomain}`, | |
| + targetOriginId: pulumi.interpolate`${branches[0].branch.branchName}.${amplify.defaultDomain}`, | |
| viewerProtocolPolicy: "redirect-to-https", | |
| - // Lambda@Edge associations for origin request and response | |
| + // Lambda@Edge association for origin request | |
| lambdaFunctionAssociations: [ | |
| { | |
| eventType: "origin-request", | |
| - lambdaArn: originRouterVersionArn, | |
| - includeBody: false, | |
| - }, | |
| - { | |
| - eventType: "origin-response", | |
| - lambdaArn: originResponseVersionArn, | |
| + lambdaArn: lambdaVersionArn, | |
| includeBody: false, | |
| }, | |
| ], | |
| - // Disable caching and forward all viewer headers (except Host) using managed policies | |
| - cachePolicyId: cachingDisabledPolicy, | |
| - originRequestPolicyId: allViewerExceptHostHeaderPolicy, | |
| - responseHeadersPolicyId: responseHeadersPolicy.id, | |
| + // Forward cookies to enable Lambda@Edge to read them | |
| + forwardedValues: { | |
| + cookies: { | |
| + forward: "whitelist", | |
| + whitelistedNames: [`deployment-${stack}`], | |
| + }, | |
| + queryString: false, | |
| + headers: [], | |
| + }, | |
| + minTtl: 0, | |
| + defaultTtl: 86400, | |
| + maxTtl: 31536000, | |
| }, | |
| - aliases: [config.require("domain")], | |
| enabled: true, | |
| httpVersion: "http2", | |
| isIpv6Enabled: true, | |
| @@ -776,7 +394,7 @@ const distribution = new aws.cloudfront.Distribution( | |
| customHeaders: [ | |
| { | |
| name: "X-Stack-Name", | |
| - value: getCookieStackName(stack), | |
| + value: stack, | |
| }, | |
| { | |
| name: "X-Amplify-Branch-Mappings", | |
| @@ -801,7 +419,7 @@ const distribution = new aws.cloudfront.Distribution( | |
| Name: `pos-frontend-distribution-${stack}`, | |
| }, | |
| viewerCertificate: { | |
| - acmCertificateArn: certificate.arn, | |
| + acmCertificateArn: wildcardCertificate.arn, | |
| sslSupportMethod: "sni-only", | |
| }, | |
| }, | |
| @@ -814,5 +432,4 @@ export default { | |
| branches, | |
| distribution, | |
| cookieName, | |
| - webAcl, | |
| }; | |
| diff --git a/kubb.config.ts b/kubb.config.ts | |
| index 14e3321d..e1c9315d 100644 | |
| --- a/kubb.config.ts | |
| +++ b/kubb.config.ts | |
| @@ -109,60 +109,6 @@ export default defineConfig(async () => { | |
| console.error("Failed to fetch spring doc:", error); | |
| } | |
| - // try fetching phoenix config | |
| - try { | |
| - const phoenixDoc = await fetch("http://localhost:8081/swagger/doc.json"); | |
| - const phoenixDocJson = await phoenixDoc.json(); | |
| - | |
| - configs.push({ | |
| - root: ".", | |
| - input: { | |
| - data: phoenixDocJson, | |
| - }, | |
| - output: { | |
| - path: "./src/phoenix-generated", | |
| - clean: true, | |
| - }, | |
| - hooks: { | |
| - done: ["npx prettier --write ./src/phoenix-generated"], | |
| - }, | |
| - plugins: [ | |
| - pluginOas({ oasClass: Oas, output: false }), | |
| - createSwaggerTs({ | |
| - enumType: "enum", | |
| - }), | |
| - pluginClient({ | |
| - client: { | |
| - importPath: "../../config/phoenix-client", | |
| - }, | |
| - include: [ | |
| - { type: "operationId", pattern: "updateOrderItemDecision" }, | |
| - { type: "operationId", pattern: "createWebsocketConnection" }, | |
| - { type: "operationId", pattern: "removeWebsocketConnection" }, | |
| - { type: "operationId", pattern: "getTransactionByTransactionItem" }, | |
| - ], | |
| - }), | |
| - pluginTanstackQuery({ | |
| - framework: "react", | |
| - infinite: false, | |
| - client: { | |
| - importPath: "../../config/phoenix-client", | |
| - }, | |
| - output: { | |
| - path: "./hooks", | |
| - }, | |
| - mutate: { | |
| - variablesType: "mutate", | |
| - methods: ["post", "put", "delete", "patch"], | |
| - }, | |
| - templates, | |
| - }), | |
| - ], | |
| - }); | |
| - } catch (error) { | |
| - console.error("Failed to fetch phoenix doc:", error); | |
| - } | |
| - | |
| // Always add the POSServiceModel config | |
| configs.push({ | |
| root: ".", | |
| diff --git a/lambda-edge/origin-response.js b/lambda-edge/origin-response.js | |
| deleted file mode 100644 | |
| index 7876a57e..00000000 | |
| --- a/lambda-edge/origin-response.js | |
| +++ /dev/null | |
| @@ -1,80 +0,0 @@ | |
| -"use strict"; | |
| - | |
| -exports.handler = async (event, ctx, callback) => { | |
| - const request = event.Records[0].cf.request; | |
| - const response = event.Records[0].cf.response; | |
| - | |
| - try { | |
| - // Extract the origin domain that was actually used | |
| - const originDomain = | |
| - request.origin && request.origin.custom | |
| - ? request.origin.custom.domainName | |
| - : "unknown"; | |
| - | |
| - // Extract stack name from custom headers (passed from CloudFront origin config) | |
| - let stack = "prod"; // default value | |
| - let branchMappings = {}; | |
| - | |
| - if ( | |
| - request.origin && | |
| - request.origin.custom && | |
| - request.origin.custom.customHeaders | |
| - ) { | |
| - const stackHeader = request.origin.custom.customHeaders["x-stack-name"]; | |
| - if (stackHeader && stackHeader[0]) { | |
| - stack = stackHeader[0].value; | |
| - } | |
| - | |
| - const branchMappingsHeader = | |
| - request.origin.custom.customHeaders["x-amplify-branch-mappings"]; | |
| - if (branchMappingsHeader && branchMappingsHeader[0]) { | |
| - branchMappings = JSON.parse(branchMappingsHeader[0].value); | |
| - } | |
| - } | |
| - | |
| - console.log(`Origin domain served: ${originDomain}`); | |
| - console.log(`Stack: ${stack}`); | |
| - console.log(`Branch mappings:`, branchMappings); | |
| - | |
| - // Determine which deployment target was served by matching the origin domain | |
| - let deploymentTarget = "UNKNOWN"; | |
| - for (const [target, domain] of Object.entries(branchMappings)) { | |
| - if (domain === originDomain) { | |
| - deploymentTarget = target; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - // Add response headers to indicate which deployment was served | |
| - response.headers["x-served-from"] = [ | |
| - { | |
| - key: "X-Served-From", | |
| - value: deploymentTarget, | |
| - }, | |
| - ]; | |
| - | |
| - response.headers["x-origin-domain"] = [ | |
| - { | |
| - key: "X-Origin-Domain", | |
| - value: originDomain, | |
| - }, | |
| - ]; | |
| - | |
| - response.headers["x-stack"] = [ | |
| - { | |
| - key: "X-Stack", | |
| - value: stack, | |
| - }, | |
| - ]; | |
| - | |
| - console.log( | |
| - `Added response headers: X-Served-From=${deploymentTarget}, X-Origin-Domain=${originDomain}, X-Stack=${stack}`, | |
| - ); | |
| - | |
| - callback(null, response); | |
| - } catch (error) { | |
| - console.error("Error in origin-response Lambda:", error); | |
| - // Continue with original response even if our logic fails | |
| - callback(null, response); | |
| - } | |
| -}; | |
| diff --git a/lambda-edge/origin-router.js b/lambda-edge/origin-router.js | |
| index cb4a3dbb..a8c67de6 100644 | |
| --- a/lambda-edge/origin-router.js | |
| +++ b/lambda-edge/origin-router.js | |
| @@ -1,74 +1,63 @@ | |
| "use strict"; | |
| -exports.handler = async (event, ctx, callback) => { | |
| +exports.handler = async (event) => { | |
| const request = event.Records[0].cf.request; | |
| - try { | |
| - const headers = request.headers; | |
| + const headers = request.headers; | |
| - // Extract stack name from custom headers passed by CloudFront | |
| - let stack = "prod"; // default value | |
| - let branchMappings = {}; | |
| - if ( | |
| - request.origin && | |
| - request.origin.custom && | |
| - request.origin.custom.customHeaders | |
| - ) { | |
| - const stackHeader = request.origin.custom.customHeaders["x-stack-name"]; | |
| - if (stackHeader && stackHeader[0]) { | |
| - stack = stackHeader[0].value; | |
| - } | |
| - const branchMappingsHeader = | |
| - request.origin.custom.customHeaders["x-amplify-branch-mappings"]; | |
| - if (branchMappingsHeader && branchMappingsHeader[0]) { | |
| - branchMappings = JSON.parse(branchMappingsHeader[0].value); | |
| - } | |
| - if (Object.keys(branchMappings).length === 0) { | |
| - throw new Error("Branch mappings are required"); | |
| - } | |
| + // Extract stack name from custom headers passed by CloudFront | |
| + let stack = "prod"; // default value | |
| + let branchMappings = {}; | |
| + if ( | |
| + request.origin && | |
| + request.origin.custom && | |
| + request.origin.custom.customHeaders | |
| + ) { | |
| + const stackHeader = request.origin.custom.customHeaders["x-stack-name"]; | |
| + if (stackHeader && stackHeader[0]) { | |
| + stack = stackHeader[0].value; | |
| } | |
| + const branchMappingsHeader = | |
| + request.origin.custom.customHeaders["x-amplify-branch-mappings"]; | |
| + if (branchMappingsHeader && branchMappingsHeader[0]) { | |
| + branchMappings = JSON.parse(branchMappingsHeader[0].value); | |
| + } | |
| + if (Object.keys(branchMappings).length === 0) { | |
| + throw new Error("Branch mappings are required"); | |
| + } | |
| + } | |
| - const cookieName = `deployment-${stack}`; | |
| - | |
| - // Parse cookies from the request | |
| - const cookies = parseCookies(headers.cookie || []); | |
| - const deploymentCookie = cookies[cookieName]; | |
| + const cookieName = `deployment-${stack}`; | |
| - console.log( | |
| - `Stack: ${stack}, Cookie ${cookieName} value: ${deploymentCookie}`, | |
| - ); | |
| + // Parse cookies from the request | |
| + const cookies = parseCookies(headers.cookie || []); | |
| + const deploymentCookie = cookies[cookieName]; | |
| - console.log(request.origin); | |
| + console.log( | |
| + `Stack: ${stack}, Cookie ${cookieName} value: ${deploymentCookie}`, | |
| + ); | |
| - // Map cookie values to origin domains | |
| - // Cookie values should be: "STABLE", "CANARY" | |
| - if (deploymentCookie) { | |
| - const targetBranch = branchMappings[deploymentCookie]; | |
| + // Map cookie values to origin domains | |
| + // Cookie values should be: "PROD", "BETA", or "GAMMA" (matching the branch names) | |
| + if (deploymentCookie) { | |
| + const targetBranch = branchMappings[deploymentCookie]; | |
| - if (targetBranch) { | |
| - request.origin.custom.domainName = targetBranch; | |
| - request.headers.host = [{ key: "host", value: targetBranch }]; | |
| - console.log(`Routing to custom origin: ${targetBranch}`); | |
| - } else { | |
| - console.log( | |
| - `Invalid cookie value: ${deploymentCookie}, using default origin`, | |
| - ); | |
| - request.origin.custom.domainName = branchMappings["STABLE"]; | |
| - request.headers.host = [ | |
| - { key: "host", value: branchMappings["STABLE"] }, | |
| - ]; | |
| - console.log(`Routing to custom origin: ${branchMappings["STABLE"]}`); | |
| - } | |
| + if (targetBranch) { | |
| + request.origin.custom.domainName = targetBranch; | |
| + request.headers.host = [{ key: "Host", value: targetBranch }]; | |
| + console.log(`Routing to custom origin: ${targetBranch}`); | |
| } else { | |
| - console.log(`No ${cookieName} cookie found, using default origin`); | |
| + console.log( | |
| + `Invalid cookie value: ${deploymentCookie}, using default origin`, | |
| + ); | |
| + request.origin.custom.domainName = branchMappings["STABLE"]; | |
| + request.headers.host = [{ key: "Host", value: branchMappings["STABLE"] }]; | |
| + console.log(`Routing to custom origin: ${branchMappings["STABLE"]}`); | |
| } | |
| - | |
| - console.log(request.headers); | |
| - | |
| - callback(null, request); | |
| - } catch (error) { | |
| - console.error(error); | |
| - callback(null, request); | |
| + } else { | |
| + console.log(`No ${cookieName} cookie found, using default origin`); | |
| } | |
| + | |
| + return request; | |
| }; | |
| function parseCookies(cookieHeaders) { | |
| diff --git a/package.json b/package.json | |
| index 0e944991..b5b7fe09 100644 | |
| --- a/package.json | |
| +++ b/package.json | |
| @@ -7,11 +7,6 @@ | |
| "@chakra-ui/icons": "^2.0.19", | |
| "@chakra-ui/react": "^2.10.7", | |
| "@chakra-ui/theme": "^3.4.6", | |
| - "@electric-sql/pglite": "^0.3.9", | |
| - "@electric-sql/pglite-react": "^0.2.27", | |
| - "@electric-sql/pglite-sync": "^0.3.13", | |
| - "@electric-sql/pglite-tools": "^0.2.14", | |
| - "@electric-sql/react": "^1.0.10", | |
| "@emotion/babel-plugin": "^11.11.0", | |
| "@emotion/react": "^11.11.1", | |
| "@faker-js/faker": "^8.4.1", | |
| @@ -49,9 +44,6 @@ | |
| "@remixicon/react": "^4.2.0", | |
| "@sentry/cli": "^2.35.0", | |
| "@sentry/react": "^7.113.0", | |
| - "@statsig/react-bindings": "^3.25.3", | |
| - "@statsig/session-replay": "^3.25.3", | |
| - "@statsig/web-analytics": "^3.25.3", | |
| "@stripe/connect-js": "^3.3.0", | |
| "@stripe/react-connect-js": "^3.3.2", | |
| "@stripe/react-stripe-js": "^2.7.0", | |
| @@ -114,7 +106,7 @@ | |
| "react-slot-counter": "^2.3.3", | |
| "react-textarea-autosize": "^8.5.6", | |
| "react-thermal-printer": "^0.21.0", | |
| - "react-use-websocket": "^4.13.0", | |
| + "react-use-websocket": "^4.8.1", | |
| "recharts": "^2.15.2", | |
| "rehype-autolink-headings": "^7.1.0", | |
| "rehype-slug": "^6.0.0", | |
| @@ -151,7 +143,7 @@ | |
| "test-storybook": "test-storybook" | |
| }, | |
| "lint-staged": { | |
| - "**/*": "prettier --write --experimental-cli --ignore-unknown" | |
| + "**/*": "prettier --write --ignore-unknown" | |
| }, | |
| "browserslist": { | |
| "production": [ | |
| @@ -182,7 +174,6 @@ | |
| "@kubb/swagger-tanstack-query": "^2.28.4", | |
| "@kubb/swagger-ts": "^2.28.4", | |
| "@mixer/parallel-prettier": "^2.0.3", | |
| - "@prettier/plugin-oxc": "^0.0.4", | |
| "@pulumi/aws": "^7.0.0", | |
| "@pulumi/awsx": "^3.0.0", | |
| "@pulumi/pulumi": "^3.113.0", | |
| @@ -221,20 +212,21 @@ | |
| "http-server": "^14.1.1", | |
| "husky": "^8.0.3", | |
| "jsdom": "^24.1.0", | |
| - "lint-staged": "^15.5.2", | |
| + "lint-staged": "^13.2.3", | |
| "msw": "2.8.4", | |
| "msw-storybook-addon": "2.0.3", | |
| "postcss": "^8.4.35", | |
| "prettier": "^3.6.0", | |
| - "prettier-plugin-organize-imports": "^4.3.0", | |
| + "prettier-plugin-organize-imports": "^3.2.4", | |
| "prop-types": "^15.8.1", | |
| "storybook": "^8.1.0", | |
| "tailwindcss": "^3.4.1", | |
| + "tempo-devtools": "^2.0.80", | |
| "ts-jest": "^29.1.4", | |
| "tsx": "^4.20.5", | |
| "vite-plugin-checker": "^0.6.4", | |
| "vite-plugin-eslint": "^1.8.1", | |
| - "vite-plugin-pwa": "^1.0.3", | |
| + "vite-plugin-pwa": "^0.20.5", | |
| "vitest": "^3.1.4", | |
| "wait-on": "^7.2.0", | |
| "webpack": "^5.89.0", | |
| diff --git a/public/sounds/notification.wav b/public/sounds/notification.wav | |
| deleted file mode 100644 | |
| index 88a18e15..00000000 | |
| Binary files a/public/sounds/notification.wav and /dev/null differ | |
| diff --git a/public/version.json b/public/version.json | |
| index cbeadc3e..1c252cf4 100644 | |
| --- a/public/version.json | |
| +++ b/public/version.json | |
| @@ -1,3 +1,3 @@ | |
| { | |
| - "version": "8091c4ddafsfasa2272c590d0e508dc3db0c777" | |
| + "version": "8091jjjjjjjjjjj2272c590d0e508dc3db0c777" | |
| } | |
| diff --git a/src/App.tsx b/src/App.tsx | |
| index 1ffd3820..2e1846dd 100644 | |
| --- a/src/App.tsx | |
| +++ b/src/App.tsx | |
| @@ -11,18 +11,18 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | |
| import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; | |
| import { FocusDialog } from "components/FocusDialog"; | |
| import { LabelPrintProvider } from "components/label/LabelPrinterContext"; | |
| -import PGliteProvider from "components/pg-lite/PGliteProvider"; | |
| import { SalePageConfigProvider } from "components/SalesScreenComponents/SalePageConfigProvider"; | |
| import { SentryErrorBoundary } from "config/sentry/SentryErrorBoundary"; | |
| import { AppVersionProvider } from "context/AppVersionContext"; | |
| import { DepartmentProvider } from "context/DepartmentContext"; | |
| import { ReactNode, Suspense, useEffect, useMemo, useState } from "react"; | |
| import { | |
| - createBrowserRouter, | |
| Outlet, | |
| RouterProvider, | |
| + createBrowserRouter, | |
| useLocation, | |
| } from "react-router-dom"; | |
| +import routes from "tempo-routes"; | |
| import { QueryParamProvider } from "use-query-params"; | |
| import { ReactRouter6Adapter } from "use-query-params/adapters/react-router-6"; | |
| import { PermissionRequiredRoute } from "./components/Auth/PermissionRequiredRoute"; | |
| @@ -47,9 +47,6 @@ const PromotionsDashboard = lazy( | |
| () => import("./pages/promotions/PromotionsDashboard"), | |
| ); | |
| const SettingsPage = lazy(() => import("./pages/Settings/SettingsPage")); | |
| -const EditSalesChannelPage = lazy( | |
| - () => import("./pages/Settings/SalesChannels/EditSalesChannelPage"), | |
| -); | |
| const TotalsReport = lazy( | |
| () => import("./pages/report/TotalsReport/TotalsReportPage"), | |
| ); | |
| @@ -207,13 +204,15 @@ const GlobalProvider = ({ children }: { children: ReactNode }) => { | |
| }, [location.pathname]); | |
| return ( | |
| - <AuthorizationContextProvider> | |
| - <SearchProvider> | |
| - <QueryParamProvider adapter={ReactRouter6Adapter}> | |
| - <AppVersionProvider>{children}</AppVersionProvider> | |
| - </QueryParamProvider> | |
| - </SearchProvider> | |
| - </AuthorizationContextProvider> | |
| + <> | |
| + <AuthorizationContextProvider> | |
| + <SearchProvider> | |
| + <QueryParamProvider adapter={ReactRouter6Adapter}> | |
| + <AppVersionProvider>{children}</AppVersionProvider> | |
| + </QueryParamProvider> | |
| + </SearchProvider> | |
| + </AuthorizationContextProvider> | |
| + </> | |
| ); | |
| }; | |
| @@ -555,15 +554,13 @@ const router = createBrowserRouter([ | |
| element: ( | |
| <DepartmentProvider> | |
| <SalePageConfigProvider> | |
| - <PGliteProvider> | |
| - <SalesContextProvider> | |
| - <FocusDialog> | |
| - <RequiresDrawerSettlement> | |
| - <SalePage /> | |
| - </RequiresDrawerSettlement> | |
| - </FocusDialog> | |
| - </SalesContextProvider> | |
| - </PGliteProvider> | |
| + <SalesContextProvider> | |
| + <FocusDialog> | |
| + <RequiresDrawerSettlement> | |
| + <SalePage /> | |
| + </RequiresDrawerSettlement> | |
| + </FocusDialog> | |
| + </SalesContextProvider> | |
| </SalePageConfigProvider> | |
| </DepartmentProvider> | |
| ), | |
| @@ -933,20 +930,6 @@ const router = createBrowserRouter([ | |
| crumb: () => "Inventory Transfers", | |
| }, | |
| }, | |
| - { | |
| - path: "/settings/sales-channels/:id/edit", | |
| - element: ( | |
| - <DepartmentProvider> | |
| - <PermissionRequiredRoute | |
| - element={EditSalesChannelPage} | |
| - permission="saleschannel/*:manage" | |
| - /> | |
| - </DepartmentProvider> | |
| - ), | |
| - handle: { | |
| - crumb: () => "Edit Sales Channel", | |
| - }, | |
| - }, | |
| { | |
| path: "/settings/*", | |
| element: ( | |
| @@ -1018,6 +1001,7 @@ const router = createBrowserRouter([ | |
| path: "*", | |
| element: <NotFoundPage />, | |
| }, | |
| + ...(import.meta.env.VITE_TEMPO ? routes : []), | |
| ]); | |
| export const App = () => { | |
| diff --git a/src/codegen/kubb/templates/templates.tsx b/src/codegen/kubb/templates/templates.tsx | |
| index 41d4333a..9abc74eb 100644 | |
| --- a/src/codegen/kubb/templates/templates.tsx | |
| +++ b/src/codegen/kubb/templates/templates.tsx | |
| @@ -35,7 +35,6 @@ export const templates = { | |
| const clientOptions = [ | |
| `method: "${client.method}"`, | |
| `url: ${client.path.template}`, | |
| - `signal: signal`, | |
| client.withQueryParams && !infinite ? "params" : undefined, | |
| client.withData && !isFormData ? "data" : undefined, | |
| client.withData && isFormData ? "data: formData" : undefined, | |
| @@ -107,7 +106,7 @@ export const templates = { | |
| return infiniteQueryOptions({ | |
| queryKey, | |
| - queryFn: async ({ pageParam, signal }) => { | |
| + queryFn: async ({ pageParam }) => { | |
| ${hook.children || ""} | |
| ${formData || ""} | |
| const res = await client<${client.generics}>({ | |
| @@ -138,7 +137,7 @@ export const templates = { | |
| return { | |
| queryKey, | |
| - queryFn: async ({ pageParam, signal }) => { | |
| + queryFn: async ({ pageParam }) => { | |
| ${hook.children || ""} | |
| ${formData || ""} | |
| const res = await client<${client.generics}>({ | |
| @@ -163,7 +162,7 @@ export const templates = { | |
| return queryOptions({ | |
| queryKey, | |
| - queryFn: async ({signal}) => { | |
| + queryFn: async () => { | |
| ${hook.children || ""} | |
| ${formData || ""} | |
| const res = await client<${client.generics}>({ | |
| @@ -194,7 +193,7 @@ export const templates = { | |
| return { | |
| queryKey, | |
| - queryFn: async ({signal}) => { | |
| + queryFn: async () => { | |
| ${hook.children || ""} | |
| ${formData || ""} | |
| const res = await client<${client.generics}>({ | |
| diff --git a/src/components/CreateItem/ConfirmCreateItemDialog.tsx b/src/components/CreateItem/ConfirmCreateItemDialog.tsx | |
| index 6241e8f1..f1caaadb 100644 | |
| --- a/src/components/CreateItem/ConfirmCreateItemDialog.tsx | |
| +++ b/src/components/CreateItem/ConfirmCreateItemDialog.tsx | |
| @@ -89,6 +89,12 @@ export const ConfirmCreateItemDialog = ({ | |
| warnings.push("The item is not being created for all stores."); | |
| } | |
| + if (values.parentCohortItem && parentItem?.packSize === 1) { | |
| + warnings.push( | |
| + "The parent item is a single pack item. Having a child of a single will likely cause inventory issues.", | |
| + ); | |
| + } | |
| + | |
| if (changedPriceFields.length > 0) { | |
| warnings.push( | |
| `The mentioned pricing fields are not same across all the entities: ${changedPriceFields.join(", ")}.`, | |
| @@ -96,7 +102,6 @@ export const ConfirmCreateItemDialog = ({ | |
| } | |
| return warnings; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| itemName, | |
| values.bottleFeeMultiplier, | |
| diff --git a/src/components/DatabaseSyncLoader.tsx b/src/components/DatabaseSyncLoader.tsx | |
| deleted file mode 100644 | |
| index 6235d50d..00000000 | |
| --- a/src/components/DatabaseSyncLoader.tsx | |
| +++ /dev/null | |
| @@ -1,101 +0,0 @@ | |
| -import { useEffect, useState } from "react"; | |
| -import { cn } from "../lib/utils"; | |
| - | |
| -interface DatabaseSyncLoaderProps { | |
| - message?: string; | |
| - showProgress?: boolean; | |
| - className?: string; | |
| -} | |
| - | |
| -export function DatabaseSyncLoader({ | |
| - message = "Syncing database...", | |
| - showProgress = false, | |
| - className, | |
| -}: DatabaseSyncLoaderProps) { | |
| - const [progress, setProgress] = useState(0); | |
| - const [dots, setDots] = useState(""); | |
| - | |
| - // Animate the progress bar if showProgress is true | |
| - useEffect(() => { | |
| - if (!showProgress) return; | |
| - | |
| - const interval = setInterval(() => { | |
| - setProgress((prev) => { | |
| - return Math.min(prev + Math.random() * 10, 90); | |
| - }); | |
| - }, 2500); | |
| - | |
| - return () => clearInterval(interval); | |
| - }, [showProgress]); | |
| - | |
| - // Animate the dots in the loading text | |
| - useEffect(() => { | |
| - const interval = setInterval(() => { | |
| - setDots((prev) => { | |
| - if (prev === "...") return ""; | |
| - return `${prev}.`; | |
| - }); | |
| - }, 500); | |
| - | |
| - return () => clearInterval(interval); | |
| - }, []); | |
| - | |
| - return ( | |
| - <div | |
| - className={cn( | |
| - "flex flex-col items-center justify-center p-8 space-y-6", | |
| - "bg-card border border-border rounded-lg shadow-sm", | |
| - "min-h-[200px] w-full max-w-md mx-auto", | |
| - className, | |
| - )} | |
| - > | |
| - {/* Animated Spinner */} | |
| - <div className="relative"> | |
| - <div className="w-12 h-12 border-4 border-muted rounded-full animate-spin border-t-primary" /> | |
| - </div> | |
| - | |
| - {/* Loading Text */} | |
| - <div className="text-center space-y-2"> | |
| - <h3 className="text-lg font-semibold text-foreground"> | |
| - {message} | |
| - {dots} | |
| - </h3> | |
| - <p className="text-sm text-muted-foreground"> | |
| - Please wait while we prepare your data | |
| - </p> | |
| - </div> | |
| - | |
| - {/* Progress Bar (optional) */} | |
| - {showProgress && ( | |
| - <div className="w-full space-y-2"> | |
| - <div className="flex justify-between text-xs text-muted-foreground"> | |
| - <span>Syncing</span> | |
| - <span>{Math.round(progress)}%</span> | |
| - </div> | |
| - <div className="w-full bg-secondary rounded-full h-2 overflow-hidden"> | |
| - <div | |
| - className="h-full bg-primary rounded-full transition-all duration-500 ease-out" | |
| - style={{ width: `${progress}%` }} | |
| - /> | |
| - </div> | |
| - </div> | |
| - )} | |
| - | |
| - {/* Database Icon */} | |
| - <div className="flex items-center space-x-2 text-xs text-muted-foreground"> | |
| - <svg | |
| - className="w-4 h-4" | |
| - fill="none" | |
| - stroke="currentColor" | |
| - viewBox="0 0 24 24" | |
| - > | |
| - <title>Database Icon</title> | |
| - <ellipse cx="12" cy="5" rx="9" ry="3" /> | |
| - <path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5" /> | |
| - <path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3" /> | |
| - </svg> | |
| - <span>Transformity Database</span> | |
| - </div> | |
| - </div> | |
| - ); | |
| -} | |
| diff --git a/src/components/Employee/EmployeeTimeTable.tsx b/src/components/Employee/EmployeeTimeTable.tsx | |
| index 3a31b235..8828e5be 100644 | |
| --- a/src/components/Employee/EmployeeTimeTable.tsx | |
| +++ b/src/components/Employee/EmployeeTimeTable.tsx | |
| @@ -253,7 +253,6 @@ export const EmployeeTimeTable = ({ | |
| ] | |
| : []), | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [handleUpdateTime, handleOnSave, isUpdatingTimePunch], | |
| ); | |
| diff --git a/src/components/EntityAssetUpload.tsx b/src/components/EntityAssetUpload.tsx | |
| index 3ddada01..5c0306f3 100644 | |
| --- a/src/components/EntityAssetUpload.tsx | |
| +++ b/src/components/EntityAssetUpload.tsx | |
| @@ -74,7 +74,6 @@ export function EntityAssetUpload({ | |
| .then((result) => { | |
| setCurrentAssetUrl(result); | |
| }); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [entity.id, entityConfig]); | |
| const handleValidationError = useCallback( | |
| diff --git a/src/components/ItemDetailComponents/AddtoListDialog.tsx b/src/components/ItemDetailComponents/AddtoListDialog.tsx | |
| index ba20d092..b43e9450 100644 | |
| --- a/src/components/ItemDetailComponents/AddtoListDialog.tsx | |
| +++ b/src/components/ItemDetailComponents/AddtoListDialog.tsx | |
| @@ -56,11 +56,9 @@ export const AddToListDialog = ({ cohortItemId }: AddToListDialogProps) => { | |
| resolver: zodResolver(AddToListSchema), | |
| }); | |
| - const reset = form.reset; | |
| - | |
| useEffect(() => { | |
| - reset({}); | |
| - }, [cohortItemId, reset]); | |
| + form.reset({}); | |
| + }, [cohortItemId]); | |
| const { mutateAsync: createItemListItem, isPending } = usePostItemListItem( | |
| form.getValues().selectedListOption?.value, | |
| diff --git a/src/components/ItemDetailComponents/EditableItemTable/EditableItemRow2.tsx b/src/components/ItemDetailComponents/EditableItemTable/EditableItemRow2.tsx | |
| index fc2dfc56..0a96d356 100644 | |
| --- a/src/components/ItemDetailComponents/EditableItemTable/EditableItemRow2.tsx | |
| +++ b/src/components/ItemDetailComponents/EditableItemTable/EditableItemRow2.tsx | |
| @@ -629,7 +629,6 @@ export const EditableItemRow2: React.FC<EditableItemRow2Props> = ({ | |
| ]; | |
| }, | |
| // Disabling because we want to use ID as a dependency | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| allPossibleEntities, | |
| nonInventory, | |
| diff --git a/src/components/ItemListsComponents/ItemListDetailPageFooter.tsx b/src/components/ItemListsComponents/ItemListDetailPageFooter.tsx | |
| index 6d1a4677..9f17f696 100644 | |
| --- a/src/components/ItemListsComponents/ItemListDetailPageFooter.tsx | |
| +++ b/src/components/ItemListsComponents/ItemListDetailPageFooter.tsx | |
| @@ -103,7 +103,6 @@ export const ItemListDetailPageFooter = ({ | |
| void debouncedChangeHandler(itemFilters); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [popoverOpen, entity.id, debouncedChangeHandler, itemFilters], | |
| ); | |
| diff --git a/src/components/ItemListsComponents/ItemListsFilters.tsx b/src/components/ItemListsComponents/ItemListsFilters.tsx | |
| index cdb76601..bd45d239 100644 | |
| --- a/src/components/ItemListsComponents/ItemListsFilters.tsx | |
| +++ b/src/components/ItemListsComponents/ItemListsFilters.tsx | |
| @@ -28,7 +28,6 @@ export const ItemListsFilters = ({ | |
| if (!searchValue && name) { | |
| setSearchValue(name); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [name]); | |
| return ( | |
| diff --git a/src/components/ItemSearchComponents/ItemSearchBoxV2.tsx b/src/components/ItemSearchComponents/ItemSearchBoxV2.tsx | |
| index baf8226e..8b7c6e64 100644 | |
| --- a/src/components/ItemSearchComponents/ItemSearchBoxV2.tsx | |
| +++ b/src/components/ItemSearchComponents/ItemSearchBoxV2.tsx | |
| @@ -24,7 +24,7 @@ export type ItemSearchBoxV2Value = { | |
| export type ItemSearchBoxV2Props = { | |
| placeholder?: string; | |
| - onSearchSelected?: (item?: EntityItemDetail) => void | Promise<void>; | |
| + onSearchSelected?: (item?: EntityItemDetail) => void; | |
| value?: ItemSearchBoxV2Value; | |
| className?: string; | |
| isDisabled?: boolean; | |
| @@ -156,11 +156,9 @@ export const ItemSearchBoxV2 = forwardRef< | |
| const itemByIdOptions = getItemByIdQueryOptions( | |
| selectedItem?.id ?? -1, | |
| ); | |
| - void queryClient | |
| - .fetchQuery(itemByIdOptions) | |
| - .then(async (response) => { | |
| - await onSearchSelected(response); | |
| - }); | |
| + void queryClient.fetchQuery(itemByIdOptions).then((response) => { | |
| + onSearchSelected(response); | |
| + }); | |
| }} | |
| onSearch={debouncedSearch} | |
| placeholder={placeholder} | |
| diff --git a/src/components/MultiplePayments.tsx b/src/components/MultiplePayments.tsx | |
| index 555e582a..2de9021b 100644 | |
| --- a/src/components/MultiplePayments.tsx | |
| +++ b/src/components/MultiplePayments.tsx | |
| @@ -58,7 +58,6 @@ import { | |
| } from "./payment/disablePaymentMethods"; | |
| import { CancelPayinButton } from "./SalesScreenComponents/Modals/CancelPayinButton"; | |
| import { PayWithHouseAccount } from "./SalesScreenComponents/Modals/payments/PayWithHouseAccount"; | |
| -import { PriceLevelHelper } from "./SalesScreenComponents/Modals/PriceLevelHelper"; | |
| import { Button, ButtonProps } from "./ui/button"; | |
| import { Separator } from "./ui/separator"; | |
| import { Slider } from "./ui/slider"; | |
| @@ -372,11 +371,6 @@ const MultiplePayments = ({ | |
| </HStack> | |
| <Divider /> | |
| </VStack> | |
| - | |
| - {/* Price Level Helper */} | |
| - <PriceLevelHelper transactionTotal={transactionTotalPrice} /> | |
| - <Divider /> | |
| - | |
| <FormControl> | |
| <FormLabel>Cash Amount:</FormLabel> | |
| <MultiplePaymentsInput | |
| @@ -637,7 +631,6 @@ const MultiplePayments = ({ | |
| }} | |
| /> | |
| <Button | |
| - type="button" | |
| tabIndex={-1} | |
| disabled={!customer?.points} | |
| onFocus={(e) => e.currentTarget.blur()} | |
| @@ -702,22 +695,12 @@ const MultiplePayments = ({ | |
| setHouseAccountAmount={(houseAccountAmount) => { | |
| dispatch({ | |
| moneyType: MoneyType.HOUSE_ACCOUNT, | |
| - amount: +houseAccountAmount, | |
| + amount: houseAccountAmount, | |
| }); | |
| }} | |
| houseAccountId={moneyState.houseAccountId ?? ""} | |
| amount={moneyState.houseAccountAmount ?? 0} | |
| - maxAmount={ | |
| - transactionTotalPrice - | |
| - moneyState.cash - | |
| - moneyState.creditCard - | |
| - moneyState.creditCard2 - | |
| - moneyState.creditCard3 - | |
| - moneyState.check - | |
| - moneyState.giftCard - | |
| - moneyState.pointsDollars - | |
| - moneyState.other | |
| - } | |
| + maxAmount={transactionTotalPrice} | |
| /> | |
| ) : ( | |
| <FormHelperText>No customer selected</FormHelperText> | |
| diff --git a/src/components/NewItem.tsx b/src/components/NewItem.tsx | |
| index 3ba5b414..ce5559b1 100644 | |
| --- a/src/components/NewItem.tsx | |
| +++ b/src/components/NewItem.tsx | |
| @@ -49,9 +49,7 @@ const NewItem = ({ onSubmit, giftCardDisclosure }: NewItemProps) => { | |
| setPrice(1); | |
| setBottleFeeMulti(0); | |
| setEnvFeeMulti(0); | |
| - setSelectedDepartment( | |
| - departments.get("Misc") || departments.values().next().value, | |
| - ); | |
| + setSelectedDepartment(departments.get("Misc")); | |
| }, | |
| }); | |
| diff --git a/src/components/PoleDisplay.tsx b/src/components/PoleDisplay.tsx | |
| new file mode 100644 | |
| index 00000000..460eeab8 | |
| --- /dev/null | |
| +++ b/src/components/PoleDisplay.tsx | |
| @@ -0,0 +1,91 @@ | |
| +import * as Sentry from "config/sentry/TransformitySentry"; | |
| +import { useCallback, useState } from "react"; | |
| +import { useEffectOnce } from "usehooks-ts"; | |
| + | |
| +const BAUD_RATE = 9600; | |
| +const encoder = new TextEncoder(); | |
| +const USB_VENDOR_ID = 4008; | |
| + | |
| +export const useRequestPoleDisplay = () => { | |
| + const requestPoleDisplay = useCallback(async () => { | |
| + if (!navigator.serial) { | |
| + return; | |
| + } | |
| + try { | |
| + return await navigator.serial.requestPort({ | |
| + // chrome://device-log | |
| + filters: [{ usbVendorId: USB_VENDOR_ID }], | |
| + }); | |
| + } catch (e) { | |
| + if (e instanceof DOMException) { | |
| + if (e.name === "NotFoundError") { | |
| + // User cancelled the request | |
| + console.warn(e); | |
| + return; | |
| + } | |
| + } | |
| + Sentry.captureException(e); | |
| + } | |
| + }, []); | |
| + return requestPoleDisplay; | |
| +}; | |
| + | |
| +const usePoleDisplay = () => { | |
| + const [device, setDevice] = useState<SerialPort>(); | |
| + | |
| + useEffectOnce(() => { | |
| + if (navigator.serial) { | |
| + navigator.serial | |
| + .getPorts() | |
| + .then((devicesT) => { | |
| + const deviceT = devicesT.find( | |
| + (deviceT) => deviceT.getInfo().usbVendorId === USB_VENDOR_ID, | |
| + ); | |
| + setDevice(deviceT); | |
| + }) | |
| + .catch((err) => { | |
| + Sentry.captureException(err); | |
| + }); | |
| + } | |
| + }); | |
| + | |
| + const sendData = useCallback( | |
| + async (display1: string, display2: string) => { | |
| + if (!device) return; | |
| + | |
| + try { | |
| + await device.open({ baudRate: BAUD_RATE }); | |
| + } catch (e) { | |
| + if (e instanceof DOMException) { | |
| + if (["InvalidStateError", "NotFoundError"].includes(e.name)) { | |
| + // The device is already open | |
| + console.warn(e); | |
| + return; | |
| + } | |
| + } | |
| + Sentry.captureException(e); | |
| + return; | |
| + } | |
| + const writer = device.writable.getWriter(); | |
| + | |
| + void writer.write(encoder.encode(String.fromCharCode(31))); // Clear | |
| + void writer.write(encoder.encode(String.fromCharCode(17))); // Welcome Message | |
| + void writer.write( | |
| + encoder.encode( | |
| + display1 + " ".substring(0, 20 - display1.length), | |
| + ), | |
| + ); | |
| + void writer.write( | |
| + encoder.encode( | |
| + display2 + " ".substring(0, 19 - display2.length), | |
| + ), | |
| + ); | |
| + await writer.close(); | |
| + await device.close(); | |
| + }, | |
| + [device], | |
| + ); | |
| + | |
| + return sendData; | |
| +}; | |
| +export default usePoleDisplay; | |
| diff --git a/src/components/PriceLevelSelect.tsx b/src/components/PriceLevelSelect.tsx | |
| index 5fbdf954..6261bc61 100644 | |
| --- a/src/components/PriceLevelSelect.tsx | |
| +++ b/src/components/PriceLevelSelect.tsx | |
| @@ -8,13 +8,11 @@ import { ComboboxSelect } from "./ui/ComboboxSelect"; | |
| export type PriceLevelSelectProps = { | |
| value: string | undefined; | |
| - salesChannelId?: number | undefined; | |
| onChange: (val: string) => void; | |
| }; | |
| export const PriceLevelSelect: React.FC<PriceLevelSelectProps> = ({ | |
| value, | |
| - salesChannelId, | |
| onChange, | |
| }) => { | |
| const [entity] = useEntitySelected(); | |
| @@ -27,7 +25,6 @@ export const PriceLevelSelect: React.FC<PriceLevelSelectProps> = ({ | |
| useExecuteSearchCohortpriceleveldbGet({ | |
| cohortId: entity?.cohortId, | |
| size: 30, | |
| - salesChannelId: salesChannelId, | |
| name: priceLevelSearch, | |
| }); | |
| @@ -36,7 +33,6 @@ export const PriceLevelSelect: React.FC<PriceLevelSelectProps> = ({ | |
| (pl) => pl.id === Number(value), | |
| ); | |
| setSelectedPriceLevel(pl); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [priceLevels]); | |
| const priceLevelOptions = useMemo( | |
| diff --git a/src/components/ReceiptPrinter.tsx b/src/components/ReceiptPrinter.tsx | |
| index a6b25261..a762961a 100644 | |
| --- a/src/components/ReceiptPrinter.tsx | |
| +++ b/src/components/ReceiptPrinter.tsx | |
| @@ -79,7 +79,6 @@ export const useReceiptPrinter: () => [ | |
| console.error(e); | |
| captureException(e); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, []); | |
| const sendDataV2 = useCallback(async (elements: JSX.Element) => { | |
| diff --git a/src/components/SalePageSyncOverlay.tsx b/src/components/SalePageSyncOverlay.tsx | |
| deleted file mode 100644 | |
| index 41447c3e..00000000 | |
| --- a/src/components/SalePageSyncOverlay.tsx | |
| +++ /dev/null | |
| @@ -1,32 +0,0 @@ | |
| -import { DatabaseSyncLoader } from "./DatabaseSyncLoader"; | |
| -import { usePGliteSync } from "./pg-lite/PGliteSyncContext"; | |
| - | |
| -interface SalePageSyncOverlayProps { | |
| - children: React.ReactNode; | |
| -} | |
| - | |
| -export const SalePageSyncOverlay: React.FC<SalePageSyncOverlayProps> = ({ | |
| - children, | |
| -}) => { | |
| - const { isSyncing } = usePGliteSync(); | |
| - | |
| - if (isSyncing) { | |
| - return ( | |
| - <div className="fixed inset-0 z-50 flex items-center justify-center bg-background/95 backdrop-blur-sm"> | |
| - <div className="text-center space-y-4"> | |
| - <DatabaseSyncLoader | |
| - message="Syncing POS database" | |
| - showProgress={true} | |
| - className="shadow-lg" | |
| - /> | |
| - <div className="text-sm text-muted-foreground max-w-md"> | |
| - <p>We're preparing your point-of-sale system.</p> | |
| - <p>This usually takes just a few moments...</p> | |
| - </div> | |
| - </div> | |
| - </div> | |
| - ); | |
| - } | |
| - | |
| - return <>{children}</>; | |
| -}; | |
| diff --git a/src/components/SalesChannels/ArchivedPaymentMethodsModal.tsx b/src/components/SalesChannels/ArchivedPaymentMethodsModal.tsx | |
| deleted file mode 100644 | |
| index ecbbece6..00000000 | |
| --- a/src/components/SalesChannels/ArchivedPaymentMethodsModal.tsx | |
| +++ /dev/null | |
| @@ -1,167 +0,0 @@ | |
| -import { Button } from "components/ui/button"; | |
| -import { | |
| - Dialog, | |
| - DialogContent, | |
| - DialogDescription, | |
| - DialogHeader, | |
| - DialogTitle, | |
| -} from "components/ui/dialog"; | |
| -import { LoadingSpinner } from "components/ui/loading-spinner"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { Archive, RotateCcw } from "lucide-react"; | |
| -import React, { useState } from "react"; | |
| -import { toast } from "sonner"; | |
| -import { | |
| - EntitySalesChannelPaymentMethod, | |
| - useSearchEntitySalesChannelPaymentMethods, | |
| - useUpdateEntitySalesChannelPaymentMethod, | |
| -} from "src/spring-generated"; | |
| - | |
| -interface ArchivedPaymentMethodsModalProps { | |
| - isOpen: boolean; | |
| - onClose: () => void; | |
| - salesChannelId: number; | |
| - onPaymentMethodUnarchived?: () => Promise<void>; | |
| -} | |
| - | |
| -export const ArchivedPaymentMethodsModal: React.FC< | |
| - ArchivedPaymentMethodsModalProps | |
| -> = ({ isOpen, onClose, salesChannelId, onPaymentMethodUnarchived }) => { | |
| - const [entity] = useEntitySelected(); | |
| - const [unarchivingIds] = useState<Set<string>>(new Set()); | |
| - | |
| - // Fetch archived payment methods | |
| - const { | |
| - data: archivedPaymentMethods, | |
| - isLoading, | |
| - refetch, | |
| - isFetching, | |
| - } = useSearchEntitySalesChannelPaymentMethods( | |
| - { | |
| - entitySalesChannelId: salesChannelId, | |
| - entityId: entity?.id || 0, | |
| - isArchived: true, | |
| - page: 0, | |
| - size: 100, | |
| - }, | |
| - { | |
| - query: { | |
| - enabled: isOpen && !!salesChannelId && !!entity?.id, | |
| - queryKey: ["archived-payment-methods", salesChannelId, entity?.id], | |
| - }, | |
| - }, | |
| - ); | |
| - | |
| - const { mutateAsync: updatePaymentMethod } = | |
| - useUpdateEntitySalesChannelPaymentMethod(); | |
| - | |
| - const handleUnarchive = async ( | |
| - paymentMethod: EntitySalesChannelPaymentMethod, | |
| - ) => { | |
| - if (!paymentMethod.id) return; | |
| - | |
| - try { | |
| - await updatePaymentMethod({ | |
| - data: { | |
| - id: paymentMethod.id, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: salesChannelId, | |
| - paymentMethodType: paymentMethod.paymentMethodType, | |
| - cohortPriceLevelId: paymentMethod.cohortPriceLevelId, | |
| - displayOnPayButton: paymentMethod.displayOnPayButton, | |
| - isArchived: false, | |
| - }, | |
| - }); | |
| - | |
| - toast.success("Payment method unarchived successfully"); | |
| - void refetch(); | |
| - await onPaymentMethodUnarchived?.(); | |
| - } catch (error) { | |
| - toast.error("Failed to unarchive payment method"); | |
| - console.error("Error unarchiving payment method:", error); | |
| - } | |
| - }; | |
| - | |
| - const formatPaymentMethodName = (type: string) => { | |
| - return type | |
| - .split("_") | |
| - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) | |
| - .join(" "); | |
| - }; | |
| - | |
| - return ( | |
| - <Dialog open={isOpen} onOpenChange={onClose}> | |
| - <DialogContent className="max-w-2xl"> | |
| - <DialogHeader> | |
| - <DialogTitle className="flex items-center gap-2"> | |
| - <Archive className="h-5 w-5" /> | |
| - Archived Payment Methods | |
| - </DialogTitle> | |
| - <DialogDescription> | |
| - View and restore archived payment methods for this sales channel. | |
| - </DialogDescription> | |
| - </DialogHeader> | |
| - | |
| - <div className="mt-4"> | |
| - {isLoading || isFetching ? ( | |
| - <div className="flex items-center justify-center py-8"> | |
| - <LoadingSpinner /> | |
| - </div> | |
| - ) : archivedPaymentMethods?.content?.length === 0 ? ( | |
| - <div className="text-center py-8 text-gray-500"> | |
| - <Archive className="h-12 w-12 mx-auto mb-4 text-gray-300" /> | |
| - <p className="text-lg font-medium">No archived payment methods</p> | |
| - <p className="text-sm"> | |
| - All payment methods for this sales channel are currently active. | |
| - </p> | |
| - </div> | |
| - ) : ( | |
| - <div className="space-y-3"> | |
| - {archivedPaymentMethods?.content?.map((paymentMethod) => ( | |
| - <div | |
| - key={paymentMethod.id} | |
| - className="flex items-center justify-between p-4 border rounded-lg bg-gray-50" | |
| - > | |
| - <div className="flex-1"> | |
| - <div className="flex items-center gap-3"> | |
| - <div> | |
| - <p className="font-medium text-gray-900"> | |
| - {formatPaymentMethodName( | |
| - paymentMethod.paymentMethodType, | |
| - )} | |
| - </p> | |
| - <p className="text-sm text-gray-500"> | |
| - ID: {paymentMethod.id} | |
| - </p> | |
| - </div> | |
| - </div> | |
| - </div> | |
| - <Button | |
| - onClick={() => handleUnarchive(paymentMethod)} | |
| - disabled={unarchivingIds.has(paymentMethod.id)} | |
| - size="sm" | |
| - variant="outline" | |
| - className="flex items-center gap-2" | |
| - > | |
| - {unarchivingIds.has(paymentMethod.id) ? ( | |
| - <LoadingSpinner className="h-3 w-3" /> | |
| - ) : ( | |
| - <RotateCcw className="h-3 w-3" /> | |
| - )} | |
| - Unarchive | |
| - </Button> | |
| - </div> | |
| - ))} | |
| - </div> | |
| - )} | |
| - </div> | |
| - | |
| - <div className="flex justify-end pt-4 border-t"> | |
| - <Button variant="outline" onClick={onClose}> | |
| - Close | |
| - </Button> | |
| - </div> | |
| - </DialogContent> | |
| - </Dialog> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SalesChannels/CreateSalesChannelWizardV2.tsx b/src/components/SalesChannels/CreateSalesChannelWizardV2.tsx | |
| deleted file mode 100644 | |
| index a9d40e64..00000000 | |
| --- a/src/components/SalesChannels/CreateSalesChannelWizardV2.tsx | |
| +++ /dev/null | |
| @@ -1,189 +0,0 @@ | |
| -import { Wizard, WizardStep } from "components/ui/wizard"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { | |
| - SalesChannelFormData, | |
| - useSalesChannelWizard, | |
| -} from "hooks/useSalesChannelWizard"; | |
| -import React, { useEffect, useMemo, useState } from "react"; | |
| -import { useForm } from "react-hook-form"; | |
| -import { SalesChannelType } from "src/constants"; | |
| -import { | |
| - EntitySalesChannel, | |
| - useExecuteSearchCohortpriceleveldbGet, | |
| - useSearchPaymentMethodTypes, | |
| -} from "src/spring-generated"; | |
| -import { SalesChannelBasicInfoStep } from "./SalesChannelBasicInfoStep"; | |
| -import { SalesChannelPaymentMethodsStep } from "./SalesChannelPaymentMethodsStep"; | |
| - | |
| -interface CreateSalesChannelWizardV2Props { | |
| - isOpen: boolean; | |
| - onClose: () => void; | |
| - onSave: (channel: EntitySalesChannel) => void; | |
| -} | |
| - | |
| -export const CreateSalesChannelWizardV2: React.FC< | |
| - CreateSalesChannelWizardV2Props | |
| -> = ({ isOpen, onClose, onSave }) => { | |
| - const [entity] = useEntitySelected(); | |
| - const [selectedDepartments, setSelectedDepartments] = useState<number[]>([]); | |
| - const [isSubmitting, setIsSubmitting] = useState(false); | |
| - | |
| - // Fetch payment method types and price levels for default values | |
| - const { data: paymentMethodTypesData } = useSearchPaymentMethodTypes({ | |
| - size: 100, | |
| - }); | |
| - | |
| - const { data: priceLevels } = useExecuteSearchCohortpriceleveldbGet({ | |
| - cohortId: entity?.cohortId, | |
| - size: 1, | |
| - }); | |
| - | |
| - const defaultValues = useMemo(() => { | |
| - return { | |
| - entityId: entity?.id, | |
| - salesChannelTypeId: SalesChannelType.UNINTEGRATED, | |
| - active: false, | |
| - taxable: false, | |
| - name: "", | |
| - autoAddNewDepartments: false, | |
| - allowNegativeInventory: false, | |
| - departmentIds: [], | |
| - paymentMethods: [], | |
| - }; | |
| - }, [entity?.id]); | |
| - | |
| - const form = useForm<SalesChannelFormData>({ | |
| - defaultValues, | |
| - }); | |
| - | |
| - // Set payment methods when data becomes available | |
| - useEffect(() => { | |
| - if (!isOpen) return; | |
| - const firstPriceLevel = priceLevels?._embedded?.cohortPriceLevelDBs?.[0]; | |
| - const availablePaymentMethods = paymentMethodTypesData?.content || []; | |
| - | |
| - if ( | |
| - availablePaymentMethods.length > 0 && | |
| - firstPriceLevel && | |
| - form.getValues("paymentMethods").length === 0 | |
| - ) { | |
| - const defaultPaymentMethods = availablePaymentMethods.map( | |
| - (type, index) => ({ | |
| - paymentMethodType: type.name, | |
| - cohortPriceLevelId: firstPriceLevel.id, | |
| - displayOnPayButton: true, | |
| - isDefault: index === 0, // First one (usually CASH) is default | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: 0, | |
| - isArchived: false, | |
| - }), | |
| - ); | |
| - | |
| - form.setValue("paymentMethods", defaultPaymentMethods); | |
| - } | |
| - }, [ | |
| - isOpen, | |
| - paymentMethodTypesData?.content, | |
| - priceLevels?._embedded?.cohortPriceLevelDBs, | |
| - entity?.id, | |
| - form, | |
| - ]); | |
| - | |
| - const handleClose = () => { | |
| - onClose(); | |
| - form.reset(); | |
| - setSelectedDepartments([]); | |
| - setIsSubmitting(false); | |
| - }; | |
| - | |
| - const { handleComplete } = useSalesChannelWizard({ | |
| - onSuccess: (channel) => { | |
| - onSave(channel); | |
| - setIsSubmitting(false); | |
| - handleClose(); | |
| - }, | |
| - onClose: handleClose, | |
| - }); | |
| - | |
| - const handleCompleteWizard = async (data?: unknown) => { | |
| - setIsSubmitting(true); | |
| - try { | |
| - await handleComplete(form.getValues()); | |
| - } catch (error) { | |
| - setIsSubmitting(false); | |
| - // Error is already handled by the hook | |
| - } | |
| - }; | |
| - | |
| - const handleReset = () => { | |
| - form.reset(defaultValues); | |
| - setSelectedDepartments([]); | |
| - setIsSubmitting(false); | |
| - }; | |
| - | |
| - // Create wizard steps | |
| - const steps: WizardStep[] = useMemo( | |
| - () => [ | |
| - { | |
| - title: "Basic Information", | |
| - description: "Enter the basic details for your sales channel", | |
| - content: ( | |
| - <SalesChannelBasicInfoStep | |
| - form={form} | |
| - selectedDepartments={selectedDepartments} | |
| - setSelectedDepartments={setSelectedDepartments} | |
| - /> | |
| - ), | |
| - validation: () => { | |
| - const values = form.getValues(); | |
| - return ( | |
| - !!values.name?.trim() && values.salesChannelTypeId !== undefined | |
| - ); | |
| - }, | |
| - }, | |
| - { | |
| - title: "Payment Methods", | |
| - description: "Configure payment methods and price levels", | |
| - content: ( | |
| - <SalesChannelPaymentMethodsStep | |
| - form={form} | |
| - paymentMethodTypes={paymentMethodTypesData?.content || []} | |
| - /> | |
| - ), | |
| - validation: () => { | |
| - const values = form.getValues(); | |
| - const hasPaymentMethods = values.paymentMethods?.length > 0; | |
| - const hasDefault = values.paymentMethods?.some((pm) => pm.isDefault); | |
| - const allHavePriceLevels = values.paymentMethods?.every( | |
| - (pm) => pm.cohortPriceLevelId && pm.cohortPriceLevelId > 0, | |
| - ); | |
| - return hasPaymentMethods && hasDefault && allHavePriceLevels; | |
| - }, | |
| - }, | |
| - ], | |
| - [ | |
| - form, | |
| - selectedDepartments, | |
| - setSelectedDepartments, | |
| - paymentMethodTypesData?.content, | |
| - ], | |
| - ); | |
| - | |
| - return ( | |
| - <Wizard | |
| - steps={steps} | |
| - isOpen={isOpen} | |
| - onClose={handleClose} | |
| - onComplete={handleCompleteWizard} | |
| - onReset={handleReset} | |
| - title="Create Sales Channel" | |
| - description="Set up a new sales channel." | |
| - completeButtonText="Create Channel" | |
| - autoResetOnComplete={false} | |
| - isLoading={isSubmitting} | |
| - form={form} | |
| - /> | |
| - ); | |
| -}; | |
| - | |
| -export default CreateSalesChannelWizardV2; | |
| diff --git a/src/components/SalesChannels/PaymentMethodManager.tsx b/src/components/SalesChannels/PaymentMethodManager.tsx | |
| deleted file mode 100644 | |
| index 686f0aac..00000000 | |
| --- a/src/components/SalesChannels/PaymentMethodManager.tsx | |
| +++ /dev/null | |
| @@ -1,474 +0,0 @@ | |
| -import { Button } from "components/ui/button"; | |
| -import { Card, CardContent, CardHeader } from "components/ui/card"; | |
| -import { | |
| - DropdownMenu, | |
| - DropdownMenuContent, | |
| - DropdownMenuItem, | |
| - DropdownMenuTrigger, | |
| -} from "components/ui/dropdown-menu"; | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { SalesChannelFormData } from "hooks/useSalesChannelWizard"; | |
| -import { Archive, ChevronDown, Loader2, Plus } from "lucide-react"; | |
| -import React, { useEffect, useMemo, useState } from "react"; | |
| -import { useFieldArray, UseFormReturn } from "react-hook-form"; | |
| -import { toast } from "sonner"; | |
| -import { | |
| - useCreateEntitySalesChannelPaymentMethod, | |
| - useExecuteSearchCohortpriceleveldbGet, | |
| - useGetEntitySalesChannelById, | |
| - useSearchEntitySalesChannelPaymentMethods, | |
| - useSearchPaymentMethodTypes, | |
| - useUpdateEntitySalesChannelPaymentMethod, | |
| - useUpsertEntitySalesChannel, | |
| -} from "src/spring-generated"; | |
| -import { extractAxios400ErrorMessage } from "utils/errors"; | |
| -import { ArchivedPaymentMethodsModal } from "./ArchivedPaymentMethodsModal"; | |
| -import { PaymentMethodTable } from "./PaymentMethodTable"; | |
| - | |
| -interface PaymentMethodManagerProps { | |
| - form: UseFormReturn<SalesChannelFormData>; | |
| - salesChannelId: number; | |
| -} | |
| - | |
| -export const PaymentMethodManager: React.FC<PaymentMethodManagerProps> = ({ | |
| - form, | |
| - salesChannelId, | |
| -}) => { | |
| - const [entity] = useEntitySelected(); | |
| - const [priceLevelSearch, setPriceLevelSearch] = useState<string>(); | |
| - const [isArchivedModalOpen, setIsArchivedModalOpen] = useState(false); | |
| - | |
| - // Fetch sales channel data to get default payment method | |
| - const { data: salesChannel } = useGetEntitySalesChannelById(salesChannelId, { | |
| - query: { | |
| - enabled: !!salesChannelId && salesChannelId > 0, | |
| - }, | |
| - }); | |
| - | |
| - // Fetch payment method types from API | |
| - const { data: paymentMethodTypesData } = useSearchPaymentMethodTypes({ | |
| - size: 100, | |
| - }); | |
| - | |
| - // Fetch existing payment methods | |
| - const { | |
| - data: existingPaymentMethods, | |
| - isLoading: isLoadingExistingPaymentMethods, | |
| - refetch: refetchPaymentMethods, | |
| - } = useSearchEntitySalesChannelPaymentMethods( | |
| - { | |
| - entitySalesChannelId: salesChannelId, | |
| - entityId: entity?.id || 0, | |
| - isArchived: false, | |
| - page: 0, | |
| - size: 100, | |
| - }, | |
| - { | |
| - query: { | |
| - enabled: !!salesChannelId && !!entity?.id, | |
| - queryKey: ["payment-methods", salesChannelId, entity?.id], | |
| - }, | |
| - }, | |
| - ); | |
| - | |
| - const { data: priceLevels, isFetching: isPriceLevelsFetching } = | |
| - useExecuteSearchCohortpriceleveldbGet({ | |
| - cohortId: entity?.cohortId, | |
| - size: 100, | |
| - name: priceLevelSearch, | |
| - }); | |
| - | |
| - const { | |
| - fields: paymentMethods, | |
| - append, | |
| - remove, | |
| - update, | |
| - } = useFieldArray({ | |
| - control: form.control, | |
| - name: "paymentMethods", | |
| - keyName: "fieldArrayUniqueId", // Use the 'id' field as the unique identifier | |
| - }); | |
| - console.log("paymentMethods", paymentMethods); | |
| - | |
| - // API mutations for auto-save | |
| - const { | |
| - mutateAsync: createPaymentMethod, | |
| - isPending: isCreatingPaymentMethod, | |
| - } = useCreateEntitySalesChannelPaymentMethod(); | |
| - const { | |
| - mutateAsync: updatePaymentMethod, | |
| - isPending: isUpdatingPaymentMethod, | |
| - } = useUpdateEntitySalesChannelPaymentMethod(); | |
| - const { mutateAsync: upsertSalesChannel, isPending: isUpdatingSalesChannel } = | |
| - useUpsertEntitySalesChannel(); | |
| - | |
| - // Loading states for specific actions | |
| - const [loadingActions, setLoadingActions] = useState<Record<string, boolean>>( | |
| - {}, | |
| - ); | |
| - | |
| - // Populate payment methods when they load from API | |
| - useEffect(() => { | |
| - console.log("existingPaymentMethods", existingPaymentMethods); | |
| - if ( | |
| - existingPaymentMethods?.content && | |
| - existingPaymentMethods.content.length > 0 | |
| - ) { | |
| - const convertedPaymentMethods = existingPaymentMethods.content.map( | |
| - (pm) => ({ | |
| - id: pm.id, // This should be the escmp_ prefixed ID | |
| - paymentMethodType: pm.paymentMethodType, | |
| - cohortPriceLevelId: pm.cohortPriceLevelId, | |
| - displayOnPayButton: pm.displayOnPayButton, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: pm.entitySalesChannelId, | |
| - isDefault: pm.id === salesChannel?.defaultPaymentMethodId, | |
| - isArchived: pm.isArchived || false, | |
| - }), | |
| - ); | |
| - | |
| - console.log("convertedPaymentMethods", convertedPaymentMethods); | |
| - form.setValue("paymentMethods", convertedPaymentMethods); | |
| - } | |
| - }, [ | |
| - existingPaymentMethods, | |
| - salesChannel?.defaultPaymentMethodId, | |
| - form, | |
| - entity?.id, | |
| - ]); | |
| - | |
| - // Memoized filtered payment method options | |
| - const availablePaymentMethodOptions = useMemo(() => { | |
| - const allTypes = paymentMethodTypesData?.content || []; | |
| - const selectedTypes = paymentMethods.map((pm) => pm.paymentMethodType); | |
| - | |
| - return allTypes | |
| - .filter((type) => !selectedTypes.includes(type.name)) | |
| - .map((type) => ({ | |
| - value: type.name, | |
| - label: type.name, | |
| - })); | |
| - }, [paymentMethodTypesData?.content, paymentMethods]); | |
| - | |
| - const addPaymentMethod = async (type: string) => { | |
| - const firstPriceLevel = priceLevels?._embedded?.cohortPriceLevelDBs?.[0]; | |
| - | |
| - const actionKey = `add-${type}`; | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: true })); | |
| - | |
| - try { | |
| - const newPaymentMethod = await createPaymentMethod({ | |
| - data: { | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: salesChannelId, | |
| - paymentMethodType: type, | |
| - cohortPriceLevelId: firstPriceLevel?.id || 0, | |
| - displayOnPayButton: true, | |
| - isArchived: false, | |
| - }, | |
| - }); | |
| - | |
| - // Add to form with the correct data from API response | |
| - append({ | |
| - id: newPaymentMethod.id, // This should be the escmp_ prefixed ID | |
| - paymentMethodType: newPaymentMethod.paymentMethodType, | |
| - cohortPriceLevelId: newPaymentMethod.cohortPriceLevelId, | |
| - displayOnPayButton: newPaymentMethod.displayOnPayButton, | |
| - isDefault: paymentMethods.length === 0, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: newPaymentMethod.entitySalesChannelId, | |
| - isArchived: newPaymentMethod.isArchived || false, | |
| - }); | |
| - | |
| - toast.success("Payment method added successfully"); | |
| - } catch (error) { | |
| - toast.error( | |
| - "Failed to add payment method: " + extractAxios400ErrorMessage(error), | |
| - ); | |
| - console.error("Error adding payment method:", error); | |
| - captureException(error); | |
| - } finally { | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: false })); | |
| - } | |
| - }; | |
| - | |
| - const removePaymentMethod = async (index: number) => { | |
| - const methodToRemove = paymentMethods[index]; | |
| - | |
| - // Prevent deletion if it's the default or the only method | |
| - if ( | |
| - !methodToRemove || | |
| - methodToRemove.isDefault || | |
| - paymentMethods.length <= 1 | |
| - ) { | |
| - toast.error( | |
| - "Cannot remove the default payment method or the last payment method", | |
| - ); | |
| - return; | |
| - } | |
| - | |
| - const actionKey = `remove-${index}`; | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: true })); | |
| - | |
| - try { | |
| - if (methodToRemove.id) { | |
| - await updatePaymentMethod({ | |
| - data: { | |
| - id: methodToRemove.id, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: salesChannelId, | |
| - paymentMethodType: methodToRemove.paymentMethodType, | |
| - cohortPriceLevelId: methodToRemove.cohortPriceLevelId, | |
| - displayOnPayButton: methodToRemove.displayOnPayButton, | |
| - isArchived: true, | |
| - }, | |
| - }); | |
| - } | |
| - | |
| - remove(index); | |
| - toast.success("Payment method archived successfully"); | |
| - } catch (error) { | |
| - toast.error( | |
| - "Failed to archive payment method: " + | |
| - extractAxios400ErrorMessage(error), | |
| - ); | |
| - console.error("Error archiving payment method:", error); | |
| - captureException(error); | |
| - } finally { | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: false })); | |
| - } | |
| - }; | |
| - | |
| - const setDefaultPaymentMethod = async (index: number) => { | |
| - const newDefaultMethod = paymentMethods[index]; | |
| - if (!newDefaultMethod?.id) return; | |
| - | |
| - const actionKey = `setDefault-${index}`; | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: true })); | |
| - | |
| - try { | |
| - // Update the sales channel with the new default payment method | |
| - await upsertSalesChannel({ | |
| - data: { | |
| - ...form.getValues(), | |
| - id: salesChannelId, | |
| - defaultPaymentMethodId: newDefaultMethod.id, | |
| - }, | |
| - }); | |
| - | |
| - // Update form state | |
| - paymentMethods.forEach((_, i) => { | |
| - const currentMethod = paymentMethods[i]; | |
| - if (currentMethod) { | |
| - update(i, { | |
| - ...currentMethod, | |
| - isDefault: i === index, | |
| - }); | |
| - } | |
| - }); | |
| - | |
| - toast.success("Default payment method updated successfully"); | |
| - } catch (error) { | |
| - toast.error( | |
| - "Failed to update default payment method: " + | |
| - extractAxios400ErrorMessage(error), | |
| - ); | |
| - console.error("Error updating default payment method:", error); | |
| - captureException(error); | |
| - } finally { | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: false })); | |
| - } | |
| - }; | |
| - | |
| - const updatePaymentMethodPriceLevel = async ( | |
| - index: number, | |
| - priceLevelId: number, | |
| - ) => { | |
| - const currentMethod = paymentMethods[index]; | |
| - if (!currentMethod?.id) return; | |
| - | |
| - const actionKey = `updatePriceLevel-${index}`; | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: true })); | |
| - | |
| - try { | |
| - await updatePaymentMethod({ | |
| - data: { | |
| - id: currentMethod.id, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: salesChannelId, | |
| - paymentMethodType: currentMethod.paymentMethodType, | |
| - cohortPriceLevelId: priceLevelId, | |
| - displayOnPayButton: currentMethod.displayOnPayButton, | |
| - isArchived: currentMethod.isArchived || false, | |
| - }, | |
| - }); | |
| - | |
| - update(index, { | |
| - ...currentMethod, | |
| - cohortPriceLevelId: priceLevelId, | |
| - }); | |
| - | |
| - toast.success("Price level updated successfully"); | |
| - } catch (error) { | |
| - toast.error( | |
| - "Failed to update price level: " + extractAxios400ErrorMessage(error), | |
| - ); | |
| - console.error("Error updating price level:", error); | |
| - captureException(error); | |
| - } finally { | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: false })); | |
| - } | |
| - }; | |
| - | |
| - const updatePaymentMethodDisplayOnPayButton = async ( | |
| - index: number, | |
| - displayOnPayButton: boolean, | |
| - ) => { | |
| - const currentMethod = paymentMethods[index]; | |
| - if (!currentMethod?.id) return; | |
| - | |
| - const actionKey = `updateDisplay-${index}`; | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: true })); | |
| - | |
| - try { | |
| - await updatePaymentMethod({ | |
| - data: { | |
| - id: currentMethod.id, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: currentMethod.entitySalesChannelId, | |
| - paymentMethodType: currentMethod.paymentMethodType, | |
| - cohortPriceLevelId: currentMethod.cohortPriceLevelId, | |
| - displayOnPayButton, | |
| - isArchived: currentMethod.isArchived || false, | |
| - }, | |
| - }); | |
| - | |
| - update(index, { | |
| - ...currentMethod, | |
| - displayOnPayButton, | |
| - }); | |
| - | |
| - toast.success("Display setting updated successfully"); | |
| - } catch (error) { | |
| - toast.error( | |
| - "Failed to update display setting: " + | |
| - extractAxios400ErrorMessage(error), | |
| - ); | |
| - console.error("Error updating display setting:", error); | |
| - captureException(error); | |
| - } finally { | |
| - setLoadingActions((prev) => ({ ...prev, [actionKey]: false })); | |
| - } | |
| - }; | |
| - | |
| - const formatPaymentMethodName = (type: string) => { | |
| - return type | |
| - .split("_") | |
| - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) | |
| - .join(" "); | |
| - }; | |
| - | |
| - if (isLoadingExistingPaymentMethods) { | |
| - return ( | |
| - <Card> | |
| - <CardContent> | |
| - <div className="flex items-center justify-center py-8"> | |
| - <div className="text-center"> | |
| - <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto mb-4"></div> | |
| - <p className="text-gray-500">Loading payment methods...</p> | |
| - </div> | |
| - </div> | |
| - </CardContent> | |
| - </Card> | |
| - ); | |
| - } | |
| - | |
| - return ( | |
| - <Card> | |
| - <CardHeader className="pb-4"> | |
| - <div className="flex items-center justify-between"> | |
| - <div className="flex items-center gap-2"> | |
| - <DropdownMenu> | |
| - <DropdownMenuTrigger asChild> | |
| - <Button | |
| - type="button" | |
| - variant="outline" | |
| - disabled={availablePaymentMethodOptions.length === 0} | |
| - > | |
| - <Plus className="w-4 h-4 mr-2" /> | |
| - Add Payment Method | |
| - <ChevronDown className="w-4 h-4 ml-2" /> | |
| - </Button> | |
| - </DropdownMenuTrigger> | |
| - <DropdownMenuContent> | |
| - {availablePaymentMethodOptions.map((option) => { | |
| - const isLoading = loadingActions[`add-${option.value}`]; | |
| - return ( | |
| - <DropdownMenuItem | |
| - key={option.value} | |
| - onClick={() => addPaymentMethod(option.value)} | |
| - disabled={isLoading} | |
| - > | |
| - {isLoading ? ( | |
| - <Loader2 className="h-3 w-3 animate-spin mr-2" /> | |
| - ) : null} | |
| - {formatPaymentMethodName(option.label)} | |
| - </DropdownMenuItem> | |
| - ); | |
| - })} | |
| - </DropdownMenuContent> | |
| - </DropdownMenu> | |
| - <Button | |
| - type="button" | |
| - variant="ghost" | |
| - size="sm" | |
| - onClick={() => setIsArchivedModalOpen(true)} | |
| - className="flex items-center gap-2" | |
| - > | |
| - <Archive className="w-4 h-4" /> | |
| - View Archived | |
| - </Button> | |
| - </div> | |
| - </div> | |
| - </CardHeader> | |
| - <CardContent> | |
| - <PaymentMethodTable | |
| - paymentMethods={paymentMethods} | |
| - priceLevels={priceLevels?._embedded?.cohortPriceLevelDBs} | |
| - isPriceLevelsFetching={isPriceLevelsFetching} | |
| - onUpdatePriceLevel={updatePaymentMethodPriceLevel} | |
| - onUpdateDisplayOnPayButton={updatePaymentMethodDisplayOnPayButton} | |
| - onSetDefault={setDefaultPaymentMethod} | |
| - onRemove={removePaymentMethod} | |
| - loadingActions={loadingActions} | |
| - isEditMode={true} | |
| - onPriceLevelSearch={setPriceLevelSearch} | |
| - /> | |
| - </CardContent> | |
| - | |
| - <ArchivedPaymentMethodsModal | |
| - isOpen={isArchivedModalOpen} | |
| - onClose={() => setIsArchivedModalOpen(false)} | |
| - salesChannelId={salesChannelId} | |
| - onPaymentMethodUnarchived={async () => { | |
| - // Refetch payment methods and update form state | |
| - const result = await refetchPaymentMethods(); | |
| - if (result.data?.content) { | |
| - const converted = result.data.content.map((pm) => ({ | |
| - id: pm.id, | |
| - paymentMethodType: pm.paymentMethodType, | |
| - cohortPriceLevelId: pm.cohortPriceLevelId, | |
| - displayOnPayButton: pm.displayOnPayButton, | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: pm.entitySalesChannelId, | |
| - isDefault: pm.id === salesChannel?.defaultPaymentMethodId, | |
| - isArchived: pm.isArchived || false, | |
| - })); | |
| - form.setValue("paymentMethods", converted); | |
| - } | |
| - }} | |
| - /> | |
| - </Card> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SalesChannels/PaymentMethodTable.tsx b/src/components/SalesChannels/PaymentMethodTable.tsx | |
| deleted file mode 100644 | |
| index d0b9139f..00000000 | |
| --- a/src/components/SalesChannels/PaymentMethodTable.tsx | |
| +++ /dev/null | |
| @@ -1,262 +0,0 @@ | |
| -import { createColumnHelper } from "@tanstack/react-table"; | |
| -import { DeleteButtonWithWarning } from "components/DeleteButtonWithWarning"; | |
| -import { TransformityTable } from "components/Table/TransformityTable"; | |
| -import { Button } from "components/ui/button"; | |
| -import { Checkbox } from "components/ui/checkbox"; | |
| -import { ComboboxSelect } from "components/ui/ComboboxSelect"; | |
| -import { Loader2, Star } from "lucide-react"; | |
| -import React, { useMemo } from "react"; | |
| -import { CohortPriceLevelDb } from "src/spring-generated"; | |
| - | |
| -export interface PaymentMethodUI { | |
| - id?: string; | |
| - paymentMethodType: string; | |
| - cohortPriceLevelId: number; | |
| - displayOnPayButton: boolean; | |
| - isDefault: boolean; | |
| - entityId: number; | |
| - entitySalesChannelId: number; | |
| - isArchived: boolean; | |
| -} | |
| - | |
| -interface PaymentMethodTableProps { | |
| - paymentMethods: PaymentMethodUI[]; | |
| - priceLevels?: CohortPriceLevelDb[]; | |
| - isPriceLevelsFetching?: boolean; | |
| - onUpdatePriceLevel: (index: number, priceLevelId: number) => void; | |
| - onUpdateDisplayOnPayButton: (index: number, display: boolean) => void; | |
| - onSetDefault: (index: number) => void; | |
| - onRemove: (index: number) => void; | |
| - // Loading states for edit mode (optional) | |
| - loadingActions?: Record<string, boolean>; | |
| - // Whether this is in edit mode (auto-save) or create mode | |
| - isEditMode?: boolean; | |
| - // Optional search handler for price levels | |
| - onPriceLevelSearch?: (search: string) => void; | |
| -} | |
| - | |
| -export const PaymentMethodTable: React.FC<PaymentMethodTableProps> = ({ | |
| - paymentMethods, | |
| - priceLevels, | |
| - isPriceLevelsFetching, | |
| - onUpdatePriceLevel, | |
| - onUpdateDisplayOnPayButton, | |
| - onSetDefault, | |
| - onRemove, | |
| - loadingActions = {}, | |
| - isEditMode = false, | |
| - onPriceLevelSearch, | |
| -}) => { | |
| - const formatPaymentMethodName = (name: string) => { | |
| - return name | |
| - .split("_") | |
| - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) | |
| - .join(" "); | |
| - }; | |
| - | |
| - const priceLevelOptions = useMemo( | |
| - () => | |
| - priceLevels?.map((priceLevel) => ({ | |
| - value: priceLevel.id!.toString(), | |
| - label: priceLevel.name, | |
| - })) || [], | |
| - [priceLevels], | |
| - ); | |
| - | |
| - // Table column helper | |
| - const columnHelper = createColumnHelper<PaymentMethodUI>(); | |
| - | |
| - const columns = useMemo( | |
| - () => [ | |
| - columnHelper.accessor("paymentMethodType", { | |
| - header: "Payment Method", | |
| - cell: ({ row }) => ( | |
| - <div className="flex items-center space-x-2"> | |
| - <span className="font-medium"> | |
| - {formatPaymentMethodName(row.original.paymentMethodType)} | |
| - </span> | |
| - {row.original.isDefault && ( | |
| - <Star className="h-4 w-4 text-primary fill-primary" /> | |
| - )} | |
| - </div> | |
| - ), | |
| - }), | |
| - columnHelper.accessor("cohortPriceLevelId", { | |
| - header: "Price Level", | |
| - cell: ({ row }) => { | |
| - const index = paymentMethods.findIndex( | |
| - (pm) => | |
| - pm.id === row.original.id || | |
| - pm.paymentMethodType === row.original.paymentMethodType, | |
| - ); | |
| - const isLoading = | |
| - isEditMode && loadingActions[`updatePriceLevel-${index}`]; | |
| - | |
| - return ( | |
| - <ComboboxSelect | |
| - options={priceLevelOptions} | |
| - value={ | |
| - row.original.cohortPriceLevelId > 0 | |
| - ? { | |
| - value: row.original.cohortPriceLevelId.toString(), | |
| - label: | |
| - priceLevels?.find( | |
| - (pl) => pl.id === row.original.cohortPriceLevelId, | |
| - )?.name || "", | |
| - } | |
| - : undefined | |
| - } | |
| - onChange={(newValue) => { | |
| - if (newValue && !isNaN(parseInt(newValue))) { | |
| - onUpdatePriceLevel(index, parseInt(newValue)); | |
| - } | |
| - }} | |
| - onSearch={onPriceLevelSearch} | |
| - placeholder="Select price level" | |
| - emptyMessage="No price level found." | |
| - isLoading={isPriceLevelsFetching || isLoading} | |
| - className="h-8 text-sm" | |
| - /> | |
| - ); | |
| - }, | |
| - }), | |
| - columnHelper.accessor("displayOnPayButton", { | |
| - header: "Show on POS", | |
| - cell: ({ row }) => { | |
| - const index = paymentMethods.findIndex( | |
| - (pm) => | |
| - pm.id === row.original.id || | |
| - pm.paymentMethodType === row.original.paymentMethodType, | |
| - ); | |
| - const isLoading = | |
| - isEditMode && loadingActions[`updateDisplay-${index}`]; | |
| - | |
| - return ( | |
| - <div className="flex items-center space-x-2"> | |
| - <Checkbox | |
| - id={`show-${row.original.id || row.original.paymentMethodType}`} | |
| - checked={row.original.displayOnPayButton} | |
| - onCheckedChange={(checked) => | |
| - onUpdateDisplayOnPayButton(index, checked as boolean) | |
| - } | |
| - disabled={isLoading} | |
| - className="data-[state=checked]:bg-primary data-[state=checked]:border-primary" | |
| - /> | |
| - <label | |
| - htmlFor={`show-${row.original.id || row.original.paymentMethodType}`} | |
| - className="text-sm cursor-pointer" | |
| - > | |
| - Visible | |
| - </label> | |
| - {isLoading && <Loader2 className="h-3 w-3 animate-spin" />} | |
| - </div> | |
| - ); | |
| - }, | |
| - }), | |
| - columnHelper.accessor("isDefault", { | |
| - header: "Default", | |
| - cell: ({ row }) => { | |
| - const index = paymentMethods.findIndex( | |
| - (pm) => | |
| - pm.id === row.original.id || | |
| - pm.paymentMethodType === row.original.paymentMethodType, | |
| - ); | |
| - const isLoading = isEditMode && loadingActions[`setDefault-${index}`]; | |
| - | |
| - return ( | |
| - <div className="flex justify-center"> | |
| - <Button | |
| - type="button" | |
| - variant={row.original.isDefault ? "default" : "outline"} | |
| - size="sm" | |
| - onClick={ | |
| - row.original.isDefault ? undefined : () => onSetDefault(index) | |
| - } | |
| - disabled={row.original.isDefault || isLoading} | |
| - className="h-6 text-xs w-20" | |
| - > | |
| - {isLoading ? ( | |
| - <Loader2 className="h-3 w-3 animate-spin" /> | |
| - ) : row.original.isDefault ? ( | |
| - "Default" | |
| - ) : ( | |
| - "Set Default" | |
| - )} | |
| - </Button> | |
| - </div> | |
| - ); | |
| - }, | |
| - }), | |
| - columnHelper.display({ | |
| - id: "actions", | |
| - header: "Actions", | |
| - cell: ({ row }) => { | |
| - const index = paymentMethods.findIndex( | |
| - (pm) => | |
| - pm.id === row.original.id || | |
| - pm.paymentMethodType === row.original.paymentMethodType, | |
| - ); | |
| - const isLoading = isEditMode && loadingActions[`remove-${index}`]; | |
| - | |
| - return ( | |
| - <div className="flex items-center gap-2"> | |
| - {isEditMode ? ( | |
| - <DeleteButtonWithWarning | |
| - onDelete={() => onRemove(index)} | |
| - disabled={ | |
| - row.original.isDefault || | |
| - paymentMethods.length <= 1 || | |
| - isLoading | |
| - } | |
| - className="h-8 text-xs text-destructive border-destructive hover:bg-destructive hover:text-destructive-foreground" | |
| - size="sm" | |
| - variant="outline" | |
| - > | |
| - {isLoading ? ( | |
| - <Loader2 className="h-3 w-3 animate-spin" /> | |
| - ) : ( | |
| - "Archive" | |
| - )} | |
| - </DeleteButtonWithWarning> | |
| - ) : ( | |
| - <Button | |
| - type="button" | |
| - onClick={() => onRemove(index)} | |
| - disabled={ | |
| - row.original.isDefault || | |
| - paymentMethods.length <= 1 || | |
| - isLoading | |
| - } | |
| - className="h-8 text-xs text-destructive border-destructive hover:bg-destructive hover:text-destructive-foreground" | |
| - size="sm" | |
| - variant="outline" | |
| - > | |
| - {isLoading ? ( | |
| - <Loader2 className="h-3 w-3 animate-spin" /> | |
| - ) : ( | |
| - "Remove" | |
| - )} | |
| - </Button> | |
| - )} | |
| - </div> | |
| - ); | |
| - }, | |
| - }), | |
| - ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| - [ | |
| - paymentMethods, | |
| - priceLevelOptions, | |
| - priceLevels, | |
| - isPriceLevelsFetching, | |
| - loadingActions, | |
| - isEditMode, | |
| - onUpdatePriceLevel, | |
| - onUpdateDisplayOnPayButton, | |
| - onSetDefault, | |
| - onRemove, | |
| - ], | |
| - ); | |
| - | |
| - return <TransformityTable data={paymentMethods} columns={columns} />; | |
| -}; | |
| diff --git a/src/components/SalesChannels/SalesChannelBasicInfoStep.tsx b/src/components/SalesChannels/SalesChannelBasicInfoStep.tsx | |
| deleted file mode 100644 | |
| index f0ad27f0..00000000 | |
| --- a/src/components/SalesChannels/SalesChannelBasicInfoStep.tsx | |
| +++ /dev/null | |
| @@ -1,221 +0,0 @@ | |
| -import { DepartmentSelect } from "components/common/DepartmentSelect"; | |
| -import { Input } from "components/ui/input"; | |
| -import { | |
| - Select, | |
| - SelectContent, | |
| - SelectItem, | |
| - SelectTrigger, | |
| - SelectValue, | |
| -} from "components/ui/select"; | |
| -import { Switch } from "components/ui/switch"; | |
| -import { SalesChannelFormData } from "hooks/useSalesChannelWizard"; | |
| -import React from "react"; | |
| -import { Controller, UseFormReturn } from "react-hook-form"; | |
| -import { SalesChannelType, salesChannelTypeOptions } from "src/constants"; | |
| -import { useListSalesChannelTypes } from "src/spring-generated"; | |
| - | |
| -interface SalesChannelBasicInfoStepProps { | |
| - form: UseFormReturn<SalesChannelFormData>; | |
| - selectedDepartments: number[]; | |
| - setSelectedDepartments: (departments: number[]) => void; | |
| -} | |
| - | |
| -export const SalesChannelBasicInfoStep: React.FC< | |
| - SalesChannelBasicInfoStepProps | |
| -> = ({ form, selectedDepartments, setSelectedDepartments }) => { | |
| - const { data: allowedTypes } = useListSalesChannelTypes({ | |
| - new: true, | |
| - }); | |
| - | |
| - const salesChannelTypeId: SalesChannelType = form.watch("salesChannelTypeId"); | |
| - | |
| - const salesChannelOptions = | |
| - salesChannelTypeOptions[ | |
| - salesChannelTypeId ?? SalesChannelType.UNINTEGRATED | |
| - ]; | |
| - | |
| - return ( | |
| - <div className="space-y-6"> | |
| - {/* Channel Name */} | |
| - <div> | |
| - <label | |
| - htmlFor="name" | |
| - className="block text-sm font-medium text-gray-700 mb-2" | |
| - > | |
| - Channel Name * | |
| - </label> | |
| - <Controller | |
| - name="name" | |
| - control={form.control} | |
| - rules={{ required: "Name is required" }} | |
| - render={({ field, fieldState: { error } }) => ( | |
| - <> | |
| - <Input | |
| - id="name" | |
| - {...field} | |
| - placeholder="Enter channel name" | |
| - className="w-full" | |
| - /> | |
| - {error && ( | |
| - <p className="text-red-500 text-sm mt-1">{error.message}</p> | |
| - )} | |
| - </> | |
| - )} | |
| - /> | |
| - </div> | |
| - | |
| - {/* Integration Type */} | |
| - {salesChannelOptions.canEditIntegrationType && ( | |
| - <div> | |
| - <label | |
| - htmlFor="channelType" | |
| - className="block text-sm font-medium text-gray-700 mb-2" | |
| - > | |
| - Integration Type * | |
| - </label> | |
| - <Controller | |
| - name="salesChannelTypeId" | |
| - control={form.control} | |
| - render={({ field }) => ( | |
| - <Select | |
| - onValueChange={(value) => field.onChange(Number(value))} | |
| - value={field.value?.toString()} | |
| - > | |
| - <SelectTrigger id="channelType"> | |
| - <SelectValue placeholder="Select integration type" /> | |
| - </SelectTrigger> | |
| - <SelectContent> | |
| - {allowedTypes?.map((type) => ( | |
| - <SelectItem key={type.id} value={type.id.toString()}> | |
| - {type.name} | |
| - </SelectItem> | |
| - ))} | |
| - </SelectContent> | |
| - </Select> | |
| - )} | |
| - /> | |
| - </div> | |
| - )} | |
| - | |
| - {/* Departments */} | |
| - <div> | |
| - <label | |
| - htmlFor="departmentIds" | |
| - className="block text-sm font-medium text-gray-700 mb-2" | |
| - > | |
| - Departments | |
| - </label> | |
| - <p className="text-sm text-gray-500 mb-3"> | |
| - Select departments that should be synced to this sales channel | |
| - </p> | |
| - <Controller | |
| - name="departmentIds" | |
| - control={form.control} | |
| - render={({ field }) => ( | |
| - <DepartmentSelect | |
| - selectedDepartments={selectedDepartments} | |
| - setSelectedDepartments={(val) => { | |
| - field.onChange(val); | |
| - setSelectedDepartments(val); | |
| - }} | |
| - /> | |
| - )} | |
| - /> | |
| - </div> | |
| - | |
| - {/* Channel Settings */} | |
| - <div> | |
| - <h3 className="text-lg font-medium text-gray-900 mb-4"> | |
| - Channel Settings | |
| - </h3> | |
| - <div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> | |
| - <div className="flex items-center justify-between rounded-lg border p-4"> | |
| - <div className="space-y-0.5"> | |
| - <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"> | |
| - Taxable | |
| - </label> | |
| - <p className="text-xs text-muted-foreground"> | |
| - Apply taxes to transactions | |
| - </p> | |
| - </div> | |
| - <Controller | |
| - name="taxable" | |
| - control={form.control} | |
| - render={({ field }) => ( | |
| - <Switch | |
| - checked={field.value} | |
| - onCheckedChange={field.onChange} | |
| - /> | |
| - )} | |
| - /> | |
| - </div> | |
| - | |
| - {salesChannelOptions.canEditActive && ( | |
| - <div className="flex items-center justify-between rounded-lg border p-4"> | |
| - <div className="space-y-0.5"> | |
| - <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"> | |
| - Active | |
| - </label> | |
| - <p className="text-xs text-muted-foreground"> | |
| - Channel is currently active | |
| - </p> | |
| - </div> | |
| - <Controller | |
| - name="active" | |
| - control={form.control} | |
| - render={({ field }) => ( | |
| - <Switch | |
| - checked={field.value} | |
| - onCheckedChange={field.onChange} | |
| - /> | |
| - )} | |
| - /> | |
| - </div> | |
| - )} | |
| - | |
| - <div className="flex items-center justify-between rounded-lg border p-4"> | |
| - <div className="space-y-0.5"> | |
| - <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"> | |
| - Auto Add New Departments | |
| - </label> | |
| - <p className="text-xs text-muted-foreground"> | |
| - Automatically add newly created departments | |
| - </p> | |
| - </div> | |
| - <Controller | |
| - name="autoAddNewDepartments" | |
| - control={form.control} | |
| - render={({ field }) => ( | |
| - <Switch | |
| - checked={field.value} | |
| - onCheckedChange={field.onChange} | |
| - /> | |
| - )} | |
| - /> | |
| - </div> | |
| - | |
| - <div className="flex items-center justify-between rounded-lg border p-4"> | |
| - <div className="space-y-0.5"> | |
| - <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"> | |
| - Allow Negative Inventory | |
| - </label> | |
| - <p className="text-xs text-muted-foreground"> | |
| - List negative inventory as in-stock | |
| - </p> | |
| - </div> | |
| - <Controller | |
| - name="allowNegativeInventory" | |
| - control={form.control} | |
| - render={({ field }) => ( | |
| - <Switch | |
| - checked={field.value} | |
| - onCheckedChange={field.onChange} | |
| - /> | |
| - )} | |
| - /> | |
| - </div> | |
| - </div> | |
| - </div> | |
| - </div> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SalesChannels/SalesChannelPaymentMethodsStep.tsx b/src/components/SalesChannels/SalesChannelPaymentMethodsStep.tsx | |
| deleted file mode 100644 | |
| index 83245982..00000000 | |
| --- a/src/components/SalesChannels/SalesChannelPaymentMethodsStep.tsx | |
| +++ /dev/null | |
| @@ -1,192 +0,0 @@ | |
| -import { Button } from "components/ui/button"; | |
| -import { Card, CardContent, CardHeader } from "components/ui/card"; | |
| -import { | |
| - DropdownMenu, | |
| - DropdownMenuContent, | |
| - DropdownMenuItem, | |
| - DropdownMenuTrigger, | |
| -} from "components/ui/dropdown-menu"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { SalesChannelFormData } from "hooks/useSalesChannelWizard"; | |
| -import { ChevronDown, Plus } from "lucide-react"; | |
| -import React, { useMemo, useState } from "react"; | |
| -import { UseFormReturn, useFieldArray } from "react-hook-form"; | |
| -import { | |
| - PaymentMethodTypeDb, | |
| - useExecuteSearchCohortpriceleveldbGet, | |
| -} from "src/spring-generated"; | |
| -import { PaymentMethodTable, PaymentMethodUI } from "./PaymentMethodTable"; | |
| - | |
| -interface SalesChannelPaymentMethodsStepProps { | |
| - form: UseFormReturn<SalesChannelFormData>; | |
| - paymentMethodTypes: PaymentMethodTypeDb[]; | |
| -} | |
| - | |
| -export const SalesChannelPaymentMethodsStep: React.FC< | |
| - SalesChannelPaymentMethodsStepProps | |
| -> = ({ form, paymentMethodTypes }) => { | |
| - const [entity] = useEntitySelected(); | |
| - const [priceLevelSearch, setPriceLevelSearch] = useState<string>(); | |
| - | |
| - // Fetch price levels from API | |
| - const { data: priceLevels, isFetching: isPriceLevelsFetching } = | |
| - useExecuteSearchCohortpriceleveldbGet({ | |
| - cohortId: entity?.cohortId, | |
| - size: 100, | |
| - name: priceLevelSearch, | |
| - }); | |
| - | |
| - const { | |
| - fields: paymentMethods, | |
| - append, | |
| - remove, | |
| - update, | |
| - } = useFieldArray({ | |
| - control: form.control, | |
| - name: "paymentMethods", | |
| - }); | |
| - | |
| - // Memoized filtered payment method options (excluding already selected types) | |
| - const availablePaymentMethodOptions = useMemo(() => { | |
| - const allTypes = paymentMethodTypes || []; | |
| - const selectedTypes = paymentMethods.map((pm) => pm.paymentMethodType); | |
| - | |
| - return allTypes | |
| - .filter((type) => !selectedTypes.includes(type.name)) | |
| - .map((type) => ({ | |
| - value: type.name, | |
| - label: type.name, | |
| - })); | |
| - }, [paymentMethodTypes, paymentMethods]); | |
| - | |
| - const formatPaymentMethodName = (name: string) => { | |
| - return name | |
| - .split("_") | |
| - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) | |
| - .join(" "); | |
| - }; | |
| - | |
| - // Simple handlers for create mode (no auto-save) | |
| - const handleUpdatePriceLevel = (index: number, priceLevelId: number) => { | |
| - const currentMethod = paymentMethods[index]; | |
| - if (currentMethod) { | |
| - update(index, { | |
| - ...currentMethod, | |
| - cohortPriceLevelId: priceLevelId, | |
| - }); | |
| - } | |
| - }; | |
| - | |
| - const handleUpdateDisplayOnPayButton = (index: number, display: boolean) => { | |
| - const currentMethod = paymentMethods[index]; | |
| - if (currentMethod) { | |
| - update(index, { | |
| - ...currentMethod, | |
| - displayOnPayButton: display, | |
| - }); | |
| - } | |
| - }; | |
| - | |
| - const handleSetDefault = (index: number) => { | |
| - paymentMethods.forEach((_, i) => { | |
| - const currentMethod = paymentMethods[i]; | |
| - if (currentMethod) { | |
| - update(i, { | |
| - ...currentMethod, | |
| - isDefault: i === index, | |
| - }); | |
| - } | |
| - }); | |
| - }; | |
| - | |
| - const handleRemove = (index: number) => { | |
| - const methodToRemove = paymentMethods[index]; | |
| - // Prevent deletion if it's the default or last method | |
| - if ( | |
| - !methodToRemove || | |
| - methodToRemove.isDefault || | |
| - paymentMethods.length <= 1 | |
| - ) { | |
| - return; | |
| - } | |
| - remove(index); | |
| - }; | |
| - | |
| - const addPaymentMethod = (type: string) => { | |
| - const firstPriceLevel = priceLevels?._embedded?.cohortPriceLevelDBs?.[0]; | |
| - const newMethod: PaymentMethodUI = { | |
| - paymentMethodType: type, | |
| - cohortPriceLevelId: firstPriceLevel?.id || 0, | |
| - displayOnPayButton: true, | |
| - isDefault: paymentMethods.length === 0, // First one is default | |
| - entityId: entity?.id || 0, | |
| - entitySalesChannelId: 0, // Will be set when sales channel is created | |
| - isArchived: false, | |
| - }; | |
| - append(newMethod); | |
| - }; | |
| - | |
| - return ( | |
| - <div className="space-y-6"> | |
| - <Card> | |
| - <CardHeader> | |
| - <div className="flex justify-between items-center"> | |
| - <div> | |
| - <h3 className="text-lg font-medium text-gray-900"> | |
| - Payment Methods | |
| - </h3> | |
| - <p className="text-sm text-gray-500"> | |
| - Configure payment methods and price levels. One method must be | |
| - set as default. | |
| - </p> | |
| - </div> | |
| - <DropdownMenu> | |
| - <DropdownMenuTrigger asChild> | |
| - <Button | |
| - type="button" | |
| - variant="outline" | |
| - disabled={availablePaymentMethodOptions.length === 0} | |
| - > | |
| - <Plus className="w-4 h-4 mr-2" /> | |
| - Add Payment Method | |
| - <ChevronDown className="w-4 h-4 ml-2" /> | |
| - </Button> | |
| - </DropdownMenuTrigger> | |
| - <DropdownMenuContent> | |
| - {availablePaymentMethodOptions.map((option) => ( | |
| - <DropdownMenuItem | |
| - key={option.value} | |
| - onClick={() => addPaymentMethod(option.value)} | |
| - > | |
| - {formatPaymentMethodName(option.label)} | |
| - </DropdownMenuItem> | |
| - ))} | |
| - </DropdownMenuContent> | |
| - </DropdownMenu> | |
| - </div> | |
| - </CardHeader> | |
| - <CardContent> | |
| - {paymentMethods.length > 0 ? ( | |
| - <PaymentMethodTable | |
| - paymentMethods={paymentMethods} | |
| - priceLevels={priceLevels?._embedded?.cohortPriceLevelDBs} | |
| - isPriceLevelsFetching={isPriceLevelsFetching} | |
| - onUpdatePriceLevel={handleUpdatePriceLevel} | |
| - onUpdateDisplayOnPayButton={handleUpdateDisplayOnPayButton} | |
| - onSetDefault={handleSetDefault} | |
| - onRemove={handleRemove} | |
| - isEditMode={false} | |
| - /> | |
| - ) : ( | |
| - <div className="text-center py-8 text-gray-500"> | |
| - <p>Loading payment methods...</p> | |
| - <p className="text-sm"> | |
| - Please wait while we load available payment methods. | |
| - </p> | |
| - </div> | |
| - )} | |
| - </CardContent> | |
| - </Card> | |
| - </div> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SalesChannels/UpsertSalesChannelDialog.tsx b/src/components/SalesChannels/UpsertSalesChannelDialog.tsx | |
| new file mode 100644 | |
| index 00000000..7bc15ac8 | |
| --- /dev/null | |
| +++ b/src/components/SalesChannels/UpsertSalesChannelDialog.tsx | |
| @@ -0,0 +1,406 @@ | |
| +import { useToast } from "@chakra-ui/react"; | |
| +import { DepartmentSelect } from "components/common/DepartmentSelect"; | |
| +import { CenteredLayout } from "components/layouts/CenteredLayout"; | |
| +import { Button } from "components/ui/button"; | |
| +import { ComboboxSelect } from "components/ui/ComboboxSelect"; | |
| +import { | |
| + Dialog, | |
| + DialogContent, | |
| + DialogFooter, | |
| + DialogHeader, | |
| + DialogTitle, | |
| +} from "components/ui/dialog"; | |
| +import { Input } from "components/ui/input"; | |
| +import { LoadingSpinner } from "components/ui/loading-spinner"; | |
| +import { | |
| + Select, | |
| + SelectContent, | |
| + SelectItem, | |
| + SelectTrigger, | |
| + SelectValue, | |
| +} from "components/ui/select"; | |
| +import { Switch } from "components/ui/switch"; | |
| +import { useEntitySelected } from "context/EntityProvider"; | |
| +import { useGetAllDepartmentsForEntity } from "hooks/useGetAllDepartmentsForEntity"; | |
| +import React, { useCallback, useEffect, useMemo, useState } from "react"; | |
| +import { Controller, useForm } from "react-hook-form"; | |
| +import { SalesChannelType, salesChannelTypeOptions } from "src/constants"; | |
| +import { | |
| + EntitySalesChannel, | |
| + UpsertSalesChannel, | |
| + useExecuteSearchCohortpriceleveldbGet, | |
| + useFindPriceLevelById, | |
| + useListSalesChannelDepartments, | |
| + useListSalesChannelTypes, | |
| + useUpsertEntitySalesChannel, | |
| +} from "src/spring-generated"; | |
| + | |
| +type UpsertSalesChannelDialogProps = { | |
| + isOpen: boolean; | |
| + onClose: () => void; | |
| + channel?: EntitySalesChannel; | |
| + onSave: (channel: EntitySalesChannel) => void; | |
| +}; | |
| + | |
| +export const UpsertSalesChannelDialog: React.FC< | |
| + UpsertSalesChannelDialogProps | |
| +> = ({ isOpen, onClose, channel, onSave }) => { | |
| + const { departmentKeyMap } = useGetAllDepartmentsForEntity(); | |
| + const [selectedDepartments, setSelectedDepartments] = useState<number[]>([]); | |
| + const [entity] = useEntitySelected(); | |
| + const { | |
| + data: entitySalesChannelDepartments, | |
| + isFetching: isLoadingSalesChannelDepartments, | |
| + } = useListSalesChannelDepartments(channel?.id ?? 0, { | |
| + query: { | |
| + enabled: !!channel?.id, | |
| + }, | |
| + }); | |
| + | |
| + const defaultValues = useMemo(() => { | |
| + return { | |
| + entityId: entity?.id, | |
| + salesChannelTypeId: | |
| + channel?.salesChannelTypeId || SalesChannelType.UNINTEGRATED, | |
| + active: channel?.active ?? false, | |
| + taxable: channel?.taxable ?? false, | |
| + accountId: channel?.accountId, | |
| + name: channel?.name, | |
| + priceLevelId: channel?.priceLevelId, | |
| + autoAddNewDepartments: channel?.autoAddNewDepartments ?? false, | |
| + allowNegativeInventory: channel?.allowNegativeInventory ?? false, | |
| + }; | |
| + }, [ | |
| + channel?.accountId, | |
| + channel?.active, | |
| + channel?.allowNegativeInventory, | |
| + channel?.autoAddNewDepartments, | |
| + channel?.name, | |
| + channel?.priceLevelId, | |
| + channel?.salesChannelTypeId, | |
| + channel?.taxable, | |
| + entity?.id, | |
| + ]); | |
| + | |
| + const { control, handleSubmit, reset, watch } = useForm<UpsertSalesChannel>({ | |
| + defaultValues: defaultValues, | |
| + }); | |
| + | |
| + useEffect(() => { | |
| + reset(defaultValues); | |
| + }, [defaultValues, reset]); | |
| + | |
| + const handleClose = useCallback(() => { | |
| + onClose(); | |
| + reset(); | |
| + setPriceLevelSearch(undefined); | |
| + }, [onClose, reset]); | |
| + const selectedPriceLevelId = watch("priceLevelId"); | |
| + const toast = useToast(); | |
| + const { data: allowedTypes } = useListSalesChannelTypes({ | |
| + new: !channel, | |
| + }); | |
| + const [priceLevelSearch, setPriceLevelSearch] = useState<string>(); | |
| + const { data: selectedPriceLevel } = useFindPriceLevelById( | |
| + selectedPriceLevelId ?? 0, | |
| + { | |
| + query: { | |
| + enabled: !!selectedPriceLevelId, | |
| + }, | |
| + }, | |
| + ); | |
| + const { data: priceLevels, isFetching: isPriceLevelsFetching } = | |
| + useExecuteSearchCohortpriceleveldbGet({ | |
| + cohortId: entity?.cohortId, | |
| + size: 30, | |
| + name: priceLevelSearch, | |
| + }); | |
| + const { mutateAsync: upsertSalesChannel, isPending: isLoading } = | |
| + useUpsertEntitySalesChannel({ | |
| + mutation: { | |
| + onSuccess: (resp) => { | |
| + toast({ | |
| + status: "success", | |
| + title: "Sales channel updated", | |
| + description: "Your sales channel has been updated", | |
| + }); | |
| + onSave(resp); | |
| + handleClose(); | |
| + }, | |
| + onError: (err) => { | |
| + toast({ | |
| + status: "error", | |
| + title: "Error", | |
| + description: "An error occurred while updating the sales channel", | |
| + }); | |
| + }, | |
| + }, | |
| + }); | |
| + | |
| + const salesChannelTypeId: SalesChannelType = watch("salesChannelTypeId"); | |
| + | |
| + useEffect(() => { | |
| + if (channel) { | |
| + if (entitySalesChannelDepartments) { | |
| + reset({ | |
| + ...channel, | |
| + departmentIds: entitySalesChannelDepartments.map( | |
| + (department) => department.id.departmentId, | |
| + ), | |
| + }); | |
| + setSelectedDepartments( | |
| + entitySalesChannelDepartments.map( | |
| + (department) => department.id.departmentId, | |
| + ), | |
| + ); | |
| + } else { | |
| + reset(channel); | |
| + } | |
| + } | |
| + }, [channel, departmentKeyMap, entitySalesChannelDepartments, reset]); | |
| + | |
| + const onSubmit = async (data: UpsertSalesChannel) => { | |
| + await upsertSalesChannel({ | |
| + data, | |
| + }); | |
| + }; | |
| + | |
| + const priceLevelOptions = useMemo( | |
| + () => | |
| + priceLevels?._embedded?.cohortPriceLevelDBs?.map((priceLevel) => ({ | |
| + value: priceLevel.id!.toString(), | |
| + label: priceLevel.name, | |
| + })) || [], | |
| + [priceLevels], | |
| + ); | |
| + | |
| + const salesChannelOptions = | |
| + salesChannelTypeOptions[ | |
| + salesChannelTypeId ?? SalesChannelType.UNINTEGRATED | |
| + ] ?? salesChannelTypeOptions[SalesChannelType.UNINTEGRATED]; | |
| + | |
| + return ( | |
| + <Dialog open={isOpen} onOpenChange={handleClose}> | |
| + <DialogContent> | |
| + <DialogHeader> | |
| + <DialogTitle>{channel ? "Edit" : "Add"} Sales Channel</DialogTitle> | |
| + </DialogHeader> | |
| + {isLoadingSalesChannelDepartments ? ( | |
| + <CenteredLayout> | |
| + <LoadingSpinner /> | |
| + </CenteredLayout> | |
| + ) : ( | |
| + <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> | |
| + <div> | |
| + <label | |
| + htmlFor="name" | |
| + className="block text-sm font-medium text-gray-700" | |
| + > | |
| + Name | |
| + </label> | |
| + <Controller | |
| + name="name" | |
| + control={control} | |
| + rules={{ required: "Name is required" }} | |
| + render={({ field, fieldState: { error } }) => ( | |
| + <> | |
| + <Input | |
| + id="name" | |
| + {...field} | |
| + placeholder="Enter channel name" | |
| + /> | |
| + {error && ( | |
| + <p className="text-red-500 text-sm mt-1"> | |
| + {error.message} | |
| + </p> | |
| + )} | |
| + </> | |
| + )} | |
| + /> | |
| + </div> | |
| + {salesChannelOptions.canEditPriceLevel && ( | |
| + <div> | |
| + <label | |
| + htmlFor="priceLevelId" | |
| + className="block text-sm font-medium text-gray-700" | |
| + > | |
| + Price Level | |
| + </label> | |
| + <Controller | |
| + name="priceLevelId" | |
| + control={control} | |
| + rules={{ required: "Price Level is required" }} | |
| + render={({ field, fieldState: { error } }) => ( | |
| + <> | |
| + <ComboboxSelect | |
| + options={priceLevelOptions} | |
| + value={ | |
| + field.value | |
| + ? { | |
| + value: field.value?.toString() || "", | |
| + label: selectedPriceLevel?.name || "", | |
| + } | |
| + : undefined | |
| + } | |
| + onChange={(newValue) => field.onChange(newValue)} | |
| + onSearch={setPriceLevelSearch} | |
| + placeholder="Select price level" | |
| + emptyMessage="No price level found." | |
| + isLoading={isPriceLevelsFetching} | |
| + /> | |
| + {error && ( | |
| + <p className="text-red-500 text-sm mt-1"> | |
| + {error.message} | |
| + </p> | |
| + )} | |
| + </> | |
| + )} | |
| + /> | |
| + </div> | |
| + )} | |
| + {salesChannelOptions.canEditIntegrationType && ( | |
| + <div> | |
| + <label | |
| + htmlFor="channelType" | |
| + className="block text-sm font-medium text-gray-700" | |
| + > | |
| + Integration Type | |
| + </label> | |
| + <Controller | |
| + name="salesChannelTypeId" | |
| + control={control} | |
| + render={({ field }) => ( | |
| + <Select | |
| + onValueChange={(value) => field.onChange(Number(value))} | |
| + value={field.value.toString()} | |
| + > | |
| + <SelectTrigger id="channelType"> | |
| + <SelectValue placeholder="Select integration type" /> | |
| + </SelectTrigger> | |
| + <SelectContent> | |
| + {allowedTypes?.map((type) => ( | |
| + <SelectItem key={type.id} value={type.id.toString()}> | |
| + {type.name} | |
| + </SelectItem> | |
| + ))} | |
| + </SelectContent> | |
| + </Select> | |
| + )} | |
| + /> | |
| + </div> | |
| + )} | |
| + <div className="flex items-center space-x-2"> | |
| + <Controller | |
| + name="taxable" | |
| + control={control} | |
| + render={({ field }) => ( | |
| + <Switch | |
| + id="taxable" | |
| + checked={field.value} | |
| + onCheckedChange={field.onChange} | |
| + /> | |
| + )} | |
| + /> | |
| + <label | |
| + htmlFor="taxable" | |
| + className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | |
| + > | |
| + Taxable | |
| + </label> | |
| + </div> | |
| + {salesChannelOptions.canEditActive && ( | |
| + <div className="flex items-center space-x-2"> | |
| + <Controller | |
| + name="active" | |
| + control={control} | |
| + render={({ field }) => ( | |
| + <Switch | |
| + id="active" | |
| + checked={field.value} | |
| + onCheckedChange={field.onChange} | |
| + /> | |
| + )} | |
| + /> | |
| + <label | |
| + htmlFor="active" | |
| + className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | |
| + > | |
| + Active | |
| + </label> | |
| + </div> | |
| + )} | |
| + | |
| + <div> | |
| + <label htmlFor="departmentIds">Departments</label> | |
| + <p className="text-sm text-gray-500"> | |
| + Select departments that should be synced to this sales channel | |
| + </p> | |
| + <Controller | |
| + name="departmentIds" | |
| + control={control} | |
| + render={({ field }) => ( | |
| + <DepartmentSelect | |
| + selectedDepartments={selectedDepartments} | |
| + setSelectedDepartments={(val) => { | |
| + field.onChange(val); | |
| + setSelectedDepartments(val); | |
| + }} | |
| + /> | |
| + )} | |
| + /> | |
| + </div> | |
| + | |
| + <div className="flex items-center space-x-2"> | |
| + <Controller | |
| + name="autoAddNewDepartments" | |
| + control={control} | |
| + render={({ field }) => ( | |
| + <Switch | |
| + id="autoAddNewDepartments" | |
| + checked={field.value} | |
| + onCheckedChange={field.onChange} | |
| + /> | |
| + )} | |
| + /> | |
| + <label | |
| + htmlFor="autoAddNewDepartments" | |
| + className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | |
| + > | |
| + Auto Add Newly Created Departments | |
| + </label> | |
| + </div> | |
| + | |
| + <div className="flex items-center space-x-2"> | |
| + <Controller | |
| + name="allowNegativeInventory" | |
| + control={control} | |
| + render={({ field }) => ( | |
| + <Switch | |
| + id="allowNegativeInventory" | |
| + checked={field.value} | |
| + onCheckedChange={field.onChange} | |
| + /> | |
| + )} | |
| + /> | |
| + <label | |
| + htmlFor="allowNegativeInventory" | |
| + className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | |
| + > | |
| + List Negative Inventory As In-Stock | |
| + </label> | |
| + </div> | |
| + | |
| + <DialogFooter> | |
| + <Button type="button" variant="outline" onClick={handleClose}> | |
| + Cancel | |
| + </Button> | |
| + <Button type="submit" isLoading={isLoading}> | |
| + Save Changes | |
| + </Button> | |
| + </DialogFooter> | |
| + </form> | |
| + )} | |
| + </DialogContent> | |
| + </Dialog> | |
| + ); | |
| +}; | |
| diff --git a/src/components/SalesReportComponents/LineChart.tsx b/src/components/SalesReportComponents/LineChart.tsx | |
| index e608a582..691ed865 100644 | |
| --- a/src/components/SalesReportComponents/LineChart.tsx | |
| +++ b/src/components/SalesReportComponents/LineChart.tsx | |
| @@ -52,7 +52,6 @@ export const LineChart: React.FC<LineChartProps> = ({ | |
| const newData = new Map([...sortedData.entries()].slice(0, numDisplayed)); | |
| setDisplayData(newData); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [data, numDisplayed]); | |
| return ( | |
| diff --git a/src/components/SalesReportComponents/PieChart.tsx b/src/components/SalesReportComponents/PieChart.tsx | |
| index 70109717..f40ce443 100644 | |
| --- a/src/components/SalesReportComponents/PieChart.tsx | |
| +++ b/src/components/SalesReportComponents/PieChart.tsx | |
| @@ -31,7 +31,6 @@ export const PieChart: React.FC<PieChartProps> = ({ id, data, isPercent }) => { | |
| }); | |
| } | |
| setDisplayData(newData); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [data, numDisplayed]); | |
| return ( | |
| diff --git a/src/components/SalesScreenComponents/Modals/CartHoldsModal.tsx b/src/components/SalesScreenComponents/Modals/CartHoldsModal.tsx | |
| index a949921e..760574db 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/CartHoldsModal.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/CartHoldsModal.tsx | |
| @@ -18,33 +18,26 @@ import { | |
| useToast, | |
| VStack, | |
| } from "@chakra-ui/react"; | |
| -import { usePGlite } from "@electric-sql/pglite-react"; | |
| import { useQueryClient } from "@tanstack/react-query"; | |
| import { DeleteButtonWithWarning } from "components/DeleteButtonWithWarning"; | |
| -import { | |
| - type RetrieveItemsByUpc, | |
| - RetrieveItemsByUpcQuery, | |
| -} from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { useTransactionReceipt } from "components/TransactionsComponents/useTransactionReceipt"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| import { useAuthorization } from "context/AuthorizationContext/useAuthorizationContext"; | |
| -import { | |
| - useEntitySelected, | |
| - useLoyaltyProgramIdOptional, | |
| -} from "context/EntityProvider"; | |
| +import { useEntity, useLoyaltyProgramIdOptional } from "context/EntityProvider"; | |
| import { useSalesContext } from "context/Sales/SalesContext"; | |
| -import type { itemT } from "context/Sales/SalesContextProvider"; | |
| +import { itemT } from "context/Sales/SalesContextProvider"; | |
| import { format } from "date-fns"; | |
| import { useCallback, useEffect, useMemo, useState } from "react"; | |
| import { useForm } from "react-hook-form"; | |
| import { Link } from "react-router-dom"; | |
| import { | |
| - type CartDiscountType, | |
| - type Discount, | |
| + CartDiscountType, | |
| + Discount, | |
| + getItemByIdQueryOptions, | |
| getLoyaltyCustomerQueryOptions, | |
| - type LoyaltyCustomer, | |
| - type TransactionDataOutput, | |
| - type TransactionOutput, | |
| + LoyaltyCustomer, | |
| + TransactionDataOutput, | |
| + TransactionOutput, | |
| TransactionStatus, | |
| useCancelTransaction, | |
| useGetLoyaltyCustomer, | |
| @@ -52,7 +45,7 @@ import { | |
| useGetTransactions, | |
| } from "src/generated"; | |
| import { | |
| - type TransactionHoldDb, | |
| + TransactionHoldDb, | |
| useCreateTransactionHold, | |
| useDeleteTransactionHold, | |
| useListHolds, | |
| @@ -82,7 +75,7 @@ const CartDeleteButton = ({ | |
| isDeleting: boolean; | |
| }) => { | |
| const { mutateAsync: cancelTransaction, isPending } = useCancelTransaction( | |
| - transactionId, | |
| + transactionId!, | |
| {}, | |
| { | |
| mutation: { | |
| @@ -152,8 +145,6 @@ export const CartHoldCard = (props: { | |
| const [loadingCart, setLoadingCart] = useState(false); | |
| const queryClient = useQueryClient(); | |
| const { id: programId } = useLoyaltyProgramIdOptional(); | |
| - const [entity] = useEntitySelected(); | |
| - const db = usePGlite(); | |
| const { closeModal, onCartDelete, transactionData } = props; | |
| const { printReceipt } = useTransactionReceipt(); | |
| @@ -252,7 +243,7 @@ export const CartHoldCard = (props: { | |
| transactionId: originalTransactionId, | |
| upsertTransactionHold: { | |
| id: "", | |
| - name: `${customer?.name ? `${customer.name} - ` : ""}${format(new Date(), "MMM dd yyyy hh:mm a")}`, | |
| + name: `${customer?.name ? customer.name + " - " : ""}${format(new Date(), "MMM dd yyyy hh:mm a")}`, | |
| }, | |
| }, | |
| }); | |
| @@ -268,35 +259,19 @@ export const CartHoldCard = (props: { | |
| const newItemDetails = new Map() as itemT; | |
| for (const item of data.transactionItems) { | |
| - if (!item.itemId) { | |
| - newItemDetails.set(item.id, { | |
| - ...item, | |
| - tax: item.tax, | |
| - taxRate: item.taxRate ?? 0, | |
| - promotionItems: item.promotionItems, | |
| - discount: item.discount ?? 0, | |
| - itemId: item.itemId, | |
| - transactionId: props.cart.transaction.id, | |
| - department: item.department ?? 0, | |
| - }); | |
| - continue; | |
| - } | |
| - const options = RetrieveItemsByUpcQuery( | |
| - entity.id, | |
| - null, | |
| - [item.itemId], | |
| - ); | |
| - const eRes = await db.query<RetrieveItemsByUpc>( | |
| - options.query, | |
| - options.params, | |
| - ); | |
| + const entityItemOptions = !!item.itemId | |
| + ? getItemByIdQueryOptions(item.itemId) | |
| + : undefined; | |
| + const entityItem = !!entityItemOptions | |
| + ? await queryClient.fetchQuery(entityItemOptions) | |
| + : undefined; | |
| newItemDetails.set(item.id, { | |
| ...item, | |
| tax: item.tax, | |
| taxRate: item.taxRate ?? 0, | |
| promotionItems: item.promotionItems, | |
| discount: item.discount ?? 0, | |
| - item: eRes.rows?.[0], | |
| + item: entityItem, | |
| itemId: item.itemId, | |
| transactionId: props.cart.transaction.id, | |
| department: item.department ?? 0, | |
| @@ -406,12 +381,15 @@ export const CartHoldsModal: React.FC<CartHoldsModalProps> = ({ | |
| isOpen, | |
| onClose, | |
| }) => { | |
| - const [entity] = useEntitySelected(); | |
| + const [entity] = useEntity(); | |
| + const queryClient = useQueryClient(); | |
| const [currentPage, setCurrentPage] = useState(1); | |
| const pageSize = 5; // Number of carts per page | |
| const { | |
| items: itemDetails = new Map(), | |
| + taxExempt, | |
| + discount, | |
| customer, | |
| clearCart, | |
| transactionId, | |
| @@ -434,7 +412,7 @@ export const CartHoldsModal: React.FC<CartHoldsModalProps> = ({ | |
| refetch: refetchHolds, | |
| } = useGetTransactions( | |
| { | |
| - entityId: entity.id, | |
| + entityId: entity?.id ?? 0, | |
| page: currentPage - 1, // API uses 0-based indexing | |
| size: pageSize, | |
| hasHold: true, // Only get transactions with holds | |
| @@ -468,10 +446,7 @@ export const CartHoldsModal: React.FC<CartHoldsModalProps> = ({ | |
| }, | |
| }, | |
| ); | |
| - const holdsMap = useMemo( | |
| - () => new Map(holdsData?.content?.map((hold) => [hold.id, hold])), | |
| - [holdsData?.content], | |
| - ); | |
| + const holdsMap = new Map(holdsData?.content?.map((hold) => [hold.id, hold])); | |
| // Use the mapped data from the API instead of localStorage, filtering out carts without ids | |
| const apiCarts: Cart[] = useMemo(() => { | |
| @@ -557,7 +532,7 @@ export const CartHoldsModal: React.FC<CartHoldsModalProps> = ({ | |
| onClose(); | |
| reset(); | |
| await overrideLogout(); | |
| - } catch { | |
| + } catch (error) { | |
| // Error handling is done in the mutation onError callback | |
| toast({ | |
| title: "Failed to save cart", | |
| @@ -623,7 +598,7 @@ export const CartHoldsModal: React.FC<CartHoldsModalProps> = ({ | |
| autoFocus | |
| width={"100%"} | |
| onFocus={(e) => e.currentTarget.select()} | |
| - defaultValue={`${customer ? `${customer.name} - ` : ""}${format(new Date(), "MMM dd yyyy")}`} | |
| + defaultValue={`${customer ? customer.name + " - " : ""}${format(new Date(), "MMM dd yyyy")}`} | |
| {...registerForm("name", { required: true })} | |
| placeholder="Cart Name" | |
| /> | |
| @@ -650,10 +625,10 @@ export const CartHoldsModal: React.FC<CartHoldsModalProps> = ({ | |
| ) : ( | |
| <> | |
| <VStack spacing={3} w="100%" flex={1}> | |
| - {apiCarts.map((cart) => ( | |
| + {apiCarts.map((cart, index) => ( | |
| <CartHoldCard | |
| cart={cart} | |
| - key={cart.transaction.id} | |
| + key={index} | |
| transactionData={ | |
| transactionData?.transactions?.find( | |
| (t) => t.id === cart.transaction.id, | |
| diff --git a/src/components/SalesScreenComponents/Modals/ManualCardPunchModal.tsx b/src/components/SalesScreenComponents/Modals/ManualCardPunchModal.tsx | |
| index 36d0c63a..784beaf1 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/ManualCardPunchModal.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/ManualCardPunchModal.tsx | |
| @@ -7,24 +7,12 @@ import StripeCardPunchIn from "components/paymentProcessor/StripeCardPunchIn"; | |
| import WorldpayManualPaymentModal from "components/paymentProcessor/worldpay/WorldpayManualPaymentModal"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| -import { | |
| - EntitySalesChannel, | |
| - EntitySalesChannelPaymentMethod, | |
| -} from "src/spring-generated"; | |
| -import { currencyFormat } from "src/utils/currencyUtils"; | |
| const apiKey = import.meta.env.VITE_APP_STRIPE_PUBLIC_KEY; | |
| -export type CreditCardPriceOption = { | |
| - method: EntitySalesChannelPaymentMethod; | |
| - total: number; | |
| -}; | |
| - | |
| export type ManualCardPunchModalProps = { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| - onSubmit: (selectedPriceOption?: CreditCardPriceOption) => void; | |
| - selectedPriceOption?: CreditCardPriceOption; | |
| - salesChannel?: EntitySalesChannel; // Make it optional for contexts without sale page config | |
| + onSubmit: () => void; | |
| }; | |
| const stripePromise = loadStripe(apiKey); | |
| @@ -32,86 +20,34 @@ export const ManualCardPunchModal = ({ | |
| isOpen, | |
| onClose, | |
| onSubmit, | |
| - selectedPriceOption, | |
| - salesChannel: propSalesChannel, | |
| }: ManualCardPunchModalProps) => { | |
| - const { | |
| - transactionTotalPrice, | |
| - salesChannel, | |
| - selectedSalesChannel: contextSelectedSalesChannel, | |
| - } = useSalesPaymentContext(); | |
| + const { transactionTotalPrice } = useSalesPaymentContext(); | |
| const [entity] = useEntitySelected(); | |
| - // Use passed salesChannel prop or fallback to the selectedSalesChannel from context or salesChannel | |
| - const selectedSalesChannel = | |
| - propSalesChannel || contextSelectedSalesChannel || salesChannel; | |
| - // Use the provided price option or fall back to default | |
| - const defaultPrice = transactionTotalPrice(); | |
| - const defaultMethod = selectedSalesChannel?.defaultPaymentMethodId; | |
| - const defaultOption = { | |
| - method: { id: defaultMethod }, | |
| - total: defaultPrice, | |
| - } as CreditCardPriceOption; | |
| - const priceToUse = selectedPriceOption?.total || defaultPrice; | |
| - | |
| const options: StripeElementsOptionsMode = { | |
| mode: "payment", | |
| currency: "usd", | |
| - amount: Math.trunc(priceToUse * 100), | |
| + amount: Math.trunc(transactionTotalPrice() * 100), | |
| paymentMethodCreation: "manual", | |
| paymentMethodTypes: ["card"], | |
| }; | |
| - const handleSubmit = () => { | |
| - onSubmit(selectedPriceOption); | |
| - }; | |
| - | |
| return ( | |
| <> | |
| {entity.paymentProcessor?.processorName?.toLowerCase() === "worldpay" && | |
| - isOpen && ( | |
| - <WorldpayManualPaymentModal | |
| - onFormSubmit={handleSubmit} | |
| - priceSelected={selectedPriceOption ?? defaultOption} | |
| - /> | |
| - )} | |
| + isOpen && <WorldpayManualPaymentModal onFormSubmit={onSubmit} />} | |
| {entity.paymentProcessor?.processorName?.toLowerCase() !== "worldpay" && ( | |
| <Modal isOpen={isOpen} onClose={onClose}> | |
| <ModalOverlay /> | |
| <ModalContent p={10}> | |
| - {/* Show selected price info */} | |
| - {selectedPriceOption && ( | |
| - <div className="mb-4 p-3 bg-gray-50 rounded-md"> | |
| - <div className="text-sm text-gray-600"> | |
| - Processing payment for:{" "} | |
| - <span className="font-semibold"> | |
| - {currencyFormat("USD", selectedPriceOption.total)} | |
| - </span> | |
| - {selectedPriceOption.method.id !== "default" && ( | |
| - <span className="text-gray-500 ml-2"> | |
| - (Payment Method: {selectedPriceOption.method.id}) | |
| - </span> | |
| - )} | |
| - </div> | |
| - </div> | |
| - )} | |
| - | |
| {entity.paymentProcessor?.processorName?.toLowerCase() === | |
| "stripe" && ( | |
| <Elements stripe={stripePromise} options={options}> | |
| - <StripeCardPunchIn | |
| - onSubmit={handleSubmit} | |
| - priceSelected={selectedPriceOption ?? defaultOption} | |
| - /> | |
| + <StripeCardPunchIn onSubmit={onSubmit} /> | |
| </Elements> | |
| )} | |
| {entity.paymentProcessor?.processorName?.toLowerCase() === | |
| - "finix" && ( | |
| - <FinixPaymentModal | |
| - onFormSubmit={handleSubmit} | |
| - priceSelected={selectedPriceOption ?? defaultOption} | |
| - /> | |
| - )} | |
| + "finix" && <FinixPaymentModal onFormSubmit={onSubmit} />} | |
| </ModalContent> | |
| </Modal> | |
| )} | |
| diff --git a/src/components/SalesScreenComponents/Modals/MultipleChoicesModal.tsx b/src/components/SalesScreenComponents/Modals/MultipleChoicesModal.tsx | |
| index 09330931..f7c5bb8c 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/MultipleChoicesModal.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/MultipleChoicesModal.tsx | |
| @@ -11,47 +11,47 @@ import { | |
| Text, | |
| UseDisclosureReturn, | |
| } from "@chakra-ui/react"; | |
| -import { RetrieveItemsByUpc } from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { useSalesContext } from "context/Sales/SalesContext"; | |
| import { useEntityConfig } from "hooks/useEntityConfig"; | |
| import { get } from "lodash-es"; | |
| import { useMemo, useRef } from "react"; | |
| +import { EntityItemDetail } from "src/generated"; | |
| import { EntityConfigKey } from "src/generated/types/EntityConfigKey"; | |
| import { USDollar } from "utils/dollarFormat"; | |
| export type MultipleChoicesModalProps = { | |
| multipleChoicesModal: UseDisclosureReturn; | |
| transactionTotalPrice: () => number; | |
| - multipleChoices: { items: RetrieveItemsByUpc[]; quantity: number }; | |
| + multipleChoices: { items: EntityItemDetail[]; quantity: number }; | |
| }; | |
| -const selectButtonBgColor = (item: RetrieveItemsByUpc) => { | |
| - const depositMultiplier = item.ci_deposit_multiplier; | |
| - if (depositMultiplier === 1) return "blue.100"; | |
| - if (depositMultiplier === 4) return "blue.200"; | |
| - if (depositMultiplier === 8) return "blue.300"; | |
| - if (depositMultiplier === 6) return "blue.400"; | |
| - if (depositMultiplier === 12) return "blue.500"; | |
| - if (depositMultiplier === 15) return "blue.600"; | |
| - if (depositMultiplier === 18) return "blue.700"; | |
| - if (depositMultiplier === 24) return "blue.800"; | |
| - if (depositMultiplier === 30) return "blue.900"; | |
| +const selectButtonBgColor = (item: EntityItemDetail) => { | |
| + if (item.cohortItem.depositMultiplier === 1) return "blue.100"; | |
| + if (item.cohortItem.depositMultiplier === 4) return "blue.200"; | |
| + if (item.cohortItem.depositMultiplier === 8) return "blue.300"; | |
| + if (item.cohortItem.depositMultiplier === 6) return "blue.400"; | |
| + if (item.cohortItem.depositMultiplier === 12) return "blue.500"; | |
| + if (item.cohortItem.depositMultiplier === 15) return "blue.600"; | |
| + if (item.cohortItem.depositMultiplier === 18) return "blue.700"; | |
| + if (item.cohortItem.depositMultiplier === 24) return "blue.800"; | |
| + if (item.cohortItem.depositMultiplier === 30) return "blue.900"; | |
| return "blue"; | |
| }; | |
| -const selectButtonTextColor = (item: RetrieveItemsByUpc) => { | |
| - const depositMultiplier = item.ci_deposit_multiplier; | |
| - if (depositMultiplier === 1) return "black"; | |
| - if (depositMultiplier === 4) return "black"; | |
| - if (depositMultiplier === 8) return "black"; | |
| +const selectButtonTextColor = (item: EntityItemDetail) => { | |
| + if (item.cohortItem.depositMultiplier === 1) return "black"; | |
| + if (item.cohortItem.depositMultiplier === 4) return "black"; | |
| + if (item.cohortItem.depositMultiplier === 8) return "black"; | |
| return "white"; | |
| }; | |
| -const createComparator = (sortConfig: string = "ci_deposit_multiplier,asc") => { | |
| +const createComparator = ( | |
| + sortConfig: string = "cohortItem.depositMultiplier,asc", | |
| +) => { | |
| const [field, direction] = sortConfig.split(","); | |
| const multiplier = direction === "desc" ? -1 : 1; | |
| - return (a: RetrieveItemsByUpc, b: RetrieveItemsByUpc) => { | |
| + return (a: EntityItemDetail, b: EntityItemDetail) => { | |
| if (!field) return 0; | |
| const valueA = get(a, field); | |
| const valueB = get(b, field); | |
| @@ -72,7 +72,7 @@ const createComparator = (sortConfig: string = "ci_deposit_multiplier,asc") => { | |
| }; | |
| }; | |
| -const fallbackComparator = createComparator("ci_deposit_multiplier,asc"); | |
| +const fallbackComparator = createComparator("cohortItem.name,asc"); | |
| export const MultipleChoicesModal: React.FC<MultipleChoicesModalProps> = ({ | |
| multipleChoicesModal, | |
| @@ -82,13 +82,13 @@ export const MultipleChoicesModal: React.FC<MultipleChoicesModalProps> = ({ | |
| const { addSingleItemToCart } = useSalesContext(); | |
| const orderMultipleItemsPopupBy = useEntityConfig( | |
| EntityConfigKey.ORDER_MULTIPLE_ITEMS_POPUP, | |
| - "ci_deposit_multiplier,asc", | |
| + "cohortItem.depositMultiplier,asc", | |
| ); | |
| const initialFocusRef = useRef(null); | |
| const comparator = useMemo(() => { | |
| const primaryComparator = createComparator(orderMultipleItemsPopupBy.value); | |
| - return (a: RetrieveItemsByUpc, b: RetrieveItemsByUpc) => { | |
| + return (a: EntityItemDetail, b: EntityItemDetail) => { | |
| const primaryComparison = primaryComparator(a, b); | |
| if (primaryComparison !== 0) return primaryComparison; | |
| return fallbackComparator(a, b); | |
| @@ -127,7 +127,7 @@ export const MultipleChoicesModal: React.FC<MultipleChoicesModalProps> = ({ | |
| {multipleChoices.items.sort(comparator).map((choice) => { | |
| return ( | |
| <Button | |
| - key={choice.ei_id} | |
| + key={choice.id} | |
| backgroundColor={selectButtonBgColor(choice)} | |
| textColor={selectButtonTextColor(choice)} | |
| overflowX={"hidden"} | |
| @@ -144,9 +144,9 @@ export const MultipleChoicesModal: React.FC<MultipleChoicesModalProps> = ({ | |
| textAlign: "left", | |
| }} | |
| > | |
| - {choice.ci_name}{" "} | |
| + {choice.cohortItem.name}{" "} | |
| </Text> | |
| - <Text>{USDollar.format(+choice.ei_price)} </Text> | |
| + <Text>{USDollar.format(choice.price)} </Text> | |
| </Button> | |
| ); | |
| })} | |
| diff --git a/src/components/SalesScreenComponents/Modals/PayWithCashModal.tsx b/src/components/SalesScreenComponents/Modals/PayWithCashModal.tsx | |
| index 07d54537..211afd3c 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/PayWithCashModal.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/PayWithCashModal.tsx | |
| @@ -37,60 +37,46 @@ export interface PayWithCashModalProps { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| openChangeDueModal: () => void; | |
| - selectedCashPaymentMethodId?: string; | |
| } | |
| export const PayWithCashModal: React.FC<PayWithCashModalProps> = ({ | |
| isOpen, | |
| onClose, | |
| openChangeDueModal, | |
| - selectedCashPaymentMethodId, | |
| }) => { | |
| const inputRef = useRef<HTMLInputElement | null>(null); | |
| const { setAmountPaid, transactionTotalPrice } = useSalesPaymentContext(); | |
| - // Get the cash total for the selected payment method | |
| - const cashTotal = transactionTotalPrice({ | |
| - paymentMethodId: selectedCashPaymentMethodId, | |
| - }); | |
| - | |
| const form = useForm<FormValues>({ | |
| resolver: zodResolver(FormSchema), | |
| defaultValues: { | |
| - customAmount: Math.max(cashTotal, 0).toString(), | |
| + customAmount: Math.max(transactionTotalPrice(), 0).toString(), | |
| }, | |
| }); | |
| const reset = form.reset; | |
| useEffect(() => { | |
| reset({ | |
| - customAmount: Math.max(cashTotal, 0).toString(), | |
| + customAmount: Math.max(transactionTotalPrice(), 0).toString(), | |
| }); | |
| - }, [reset, cashTotal]); | |
| + }, [reset, transactionTotalPrice]); | |
| const customAmount = +form.watch("customAmount"); | |
| const handleSubmit = useCallback( | |
| (values: FormValues) => { | |
| const customAmount = +values.customAmount; | |
| - if (customAmount < cashTotal) { | |
| + if (customAmount < transactionTotalPrice()) { | |
| return; | |
| } | |
| setAmountPaid({ | |
| amountPaid: customAmount, | |
| paymentForm: TransactionPaymentForm.CASH, | |
| - paymentMethodId: selectedCashPaymentMethodId, | |
| }); | |
| openChangeDueModal(); | |
| onClose(); | |
| }, | |
| - [ | |
| - onClose, | |
| - openChangeDueModal, | |
| - setAmountPaid, | |
| - cashTotal, | |
| - selectedCashPaymentMethodId, | |
| - ], | |
| + [onClose, openChangeDueModal, setAmountPaid, transactionTotalPrice], | |
| ); | |
| return ( | |
| @@ -112,7 +98,7 @@ export const PayWithCashModal: React.FC<PayWithCashModalProps> = ({ | |
| <Text> | |
| Amount Due:{" "} | |
| <strong data-testid="amount-due-value"> | |
| - {USDollar.format(cashTotal)} | |
| + {USDollar.format(transactionTotalPrice())} | |
| </strong> | |
| </Text> | |
| </Box> | |
| @@ -142,19 +128,20 @@ export const PayWithCashModal: React.FC<PayWithCashModalProps> = ({ | |
| mr={3} | |
| size="lg" | |
| colorScheme="cyan" | |
| - hidden={customAmount < cashTotal} | |
| + hidden={customAmount < transactionTotalPrice()} | |
| onFocus={(e) => e.currentTarget.blur()} | |
| isDisabled | |
| style={{ opacity: 1.0 }} | |
| data-testid="change-due-btn" | |
| > | |
| - Change Due: {USDollar.format(customAmount - cashTotal)} | |
| + Change Due:{" "} | |
| + {USDollar.format(customAmount - transactionTotalPrice())} | |
| </Button> | |
| <Spacer /> | |
| <Button | |
| colorScheme="blue" | |
| mr={3} | |
| - isDisabled={customAmount < cashTotal} | |
| + isDisabled={customAmount < transactionTotalPrice()} | |
| type="submit" | |
| data-testid="custom-amount-submit-btn" | |
| > | |
| diff --git a/src/components/SalesScreenComponents/Modals/PriceLevelHelper.tsx b/src/components/SalesScreenComponents/Modals/PriceLevelHelper.tsx | |
| deleted file mode 100644 | |
| index 537b0a91..00000000 | |
| --- a/src/components/SalesScreenComponents/Modals/PriceLevelHelper.tsx | |
| +++ /dev/null | |
| @@ -1,179 +0,0 @@ | |
| -import { Button } from "@/components/ui/button"; | |
| -import { | |
| - Collapsible, | |
| - CollapsibleContent, | |
| - CollapsibleTrigger, | |
| -} from "@/components/ui/collapsible"; | |
| -import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| -import { ChevronDown, Info } from "lucide-react"; | |
| -import { useMemo } from "react"; | |
| -import { currencyFormat } from "src/utils/currencyUtils"; | |
| - | |
| -interface PriceLevelHelperProps { | |
| - transactionTotal: number; | |
| -} | |
| - | |
| -const formatDiscount = (discount: number) => { | |
| - if (Math.abs(discount) < 0.01) { | |
| - return "NO CHANGE"; | |
| - } | |
| - const formattedAmount = currencyFormat("USD", Math.abs(discount)); | |
| - return discount > 0 ? `-${formattedAmount}` : `+${formattedAmount}`; | |
| -}; | |
| - | |
| -// Format payment method name for display | |
| -const formatPaymentMethodName = (paymentMethodType: string) => { | |
| - return paymentMethodType | |
| - .replace(/_/g, " ") | |
| - .replace(/\b\w/g, (l) => l.toUpperCase()); | |
| -}; | |
| - | |
| -export const PriceLevelHelper: React.FC<PriceLevelHelperProps> = ({ | |
| - transactionTotal, | |
| -}) => { | |
| - const { | |
| - transactionTotalPrice, | |
| - salesChannel, | |
| - paymentMethodTypeToPaymentMethod, | |
| - findBestPaymentMethod, | |
| - } = useSalesPaymentContext(); | |
| - | |
| - // Calculate prices and discount amounts for each payment form (using default if available, otherwise cheapest) | |
| - const paymentPrices = useMemo(() => { | |
| - const prices: Record<string, number> = {}; | |
| - const discounts: Record<string, number> = {}; | |
| - const defaultPaymentMethodId = salesChannel?.defaultPaymentMethodId; | |
| - | |
| - // Get prices for each payment form using the best method (default or cheapest) | |
| - if (paymentMethodTypeToPaymentMethod) { | |
| - Object.entries(paymentMethodTypeToPaymentMethod).forEach( | |
| - ([paymentForm, paymentMethods]) => { | |
| - if (paymentMethods && paymentMethods.length > 0) { | |
| - const bestMethod = findBestPaymentMethod( | |
| - paymentMethods, | |
| - defaultPaymentMethodId, | |
| - ); | |
| - if (bestMethod) { | |
| - const price = transactionTotalPrice({ | |
| - paymentMethodId: bestMethod.id, | |
| - }); | |
| - if (price !== undefined) { | |
| - prices[paymentForm] = price; | |
| - | |
| - // Calculate discount amount (positive = discount, negative = surcharge) | |
| - const discount = transactionTotal - price; | |
| - discounts[paymentForm] = discount; | |
| - } | |
| - } | |
| - } | |
| - }, | |
| - ); | |
| - } | |
| - | |
| - // Check if all prices are the same | |
| - const priceValues = Object.values(prices); | |
| - const hasSamePrice = | |
| - priceValues.length > 0 && | |
| - priceValues.every( | |
| - (price) => Math.abs(price - (priceValues[0] ?? 0)) < 0.01, | |
| - ); | |
| - | |
| - return { | |
| - prices, | |
| - discounts, | |
| - hasSamePrice, | |
| - }; | |
| - }, [ | |
| - transactionTotalPrice, | |
| - paymentMethodTypeToPaymentMethod, | |
| - transactionTotal, | |
| - salesChannel?.defaultPaymentMethodId, | |
| - findBestPaymentMethod, | |
| - ]); | |
| - | |
| - // If all prices are the same, return null | |
| - if (paymentPrices.hasSamePrice) { | |
| - return null; | |
| - } | |
| - | |
| - return ( | |
| - <Collapsible> | |
| - <CollapsibleTrigger asChild> | |
| - <Button | |
| - variant="ghost" | |
| - className="w-full flex items-center justify-between p-2 text-sm font-medium text-gray-600 hover:bg-gray-50" | |
| - > | |
| - <div className="flex items-center gap-2"> | |
| - <Info className="w-4 h-4" /> | |
| - <span>Payment Method Discounts</span> | |
| - </div> | |
| - <ChevronDown className="w-4 h-4 transition-transform duration-200 group-data-[state=open]:rotate-180" /> | |
| - </Button> | |
| - </CollapsibleTrigger> | |
| - | |
| - <CollapsibleContent> | |
| - <div className="mt-3 p-3 bg-gray-50 rounded-md border border-gray-200"> | |
| - <div className="text-sm text-gray-600 mb-2 text-center"> | |
| - Below are the discounts needed to reach each payment form price | |
| - level (using default payment method if available, otherwise cheapest | |
| - price) | |
| - </div> | |
| - | |
| - <div className="space-y-2"> | |
| - {(() => { | |
| - // Group payment forms by discount amount | |
| - const groupedByDiscount: Record<string, string[]> = {}; | |
| - | |
| - Object.entries(paymentPrices.discounts).forEach( | |
| - ([paymentForm, discount]) => { | |
| - const discountKey = discount.toFixed(2); // Use 2 decimal places as key | |
| - if (!groupedByDiscount[discountKey]) { | |
| - groupedByDiscount[discountKey] = []; | |
| - } | |
| - groupedByDiscount[discountKey].push(paymentForm); | |
| - }, | |
| - ); | |
| - | |
| - // Sort discount amounts (cheapest first) | |
| - const sortedDiscounts = Object.keys(groupedByDiscount).sort( | |
| - (a, b) => parseFloat(a) - parseFloat(b), | |
| - ); | |
| - | |
| - return sortedDiscounts.map((discountKey) => { | |
| - const discount = parseFloat(discountKey); | |
| - const paymentForms = groupedByDiscount[discountKey]; | |
| - const isDiscount = discount > 0.01; | |
| - const isSurcharge = discount < -0.01; | |
| - const noChange = Math.abs(discount) < 0.01; | |
| - | |
| - if (!paymentForms) return null; | |
| - | |
| - return ( | |
| - <div | |
| - key={discountKey} | |
| - className="flex justify-between items-center p-2 bg-white rounded border border-gray-200" | |
| - > | |
| - <span className="text-sm font-medium"> | |
| - {paymentForms.map(formatPaymentMethodName).join(", ")}: | |
| - </span> | |
| - <span | |
| - className={`text-sm font-semibold ${ | |
| - isDiscount | |
| - ? "text-green-600" | |
| - : isSurcharge | |
| - ? "text-red-600" | |
| - : "text-gray-600" | |
| - }`} | |
| - > | |
| - {formatDiscount(discount)} | |
| - </span> | |
| - </div> | |
| - ); | |
| - }); | |
| - })()} | |
| - </div> | |
| - </div> | |
| - </CollapsibleContent> | |
| - </Collapsible> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SalesScreenComponents/Modals/QuickItemEditModal.tsx b/src/components/SalesScreenComponents/Modals/QuickItemEditModal.tsx | |
| index 6c973fd2..3b9c823f 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/QuickItemEditModal.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/QuickItemEditModal.tsx | |
| @@ -53,7 +53,7 @@ export interface QuickItemEditModalProps { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| selectedCohortItemId: CohortItem["id"]; | |
| - onUpdateSuccess?: (item: EntityItemDetail) => void | Promise<void>; | |
| + onUpdateSuccess?: (item: EntityItemDetail) => void; | |
| } | |
| export const QuickItemEditModal: React.FC<QuickItemEditModalProps> = ({ | |
| @@ -82,7 +82,6 @@ export const QuickItemEditModal: React.FC<QuickItemEditModalProps> = ({ | |
| const isInactive = useMemo( | |
| () => itemDetails?.itemTypeId === ItemTypeEnum.Inactive, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [entity.id, itemDetails?.itemTypeId], | |
| ); | |
| @@ -110,7 +109,7 @@ export const QuickItemEditModal: React.FC<QuickItemEditModalProps> = ({ | |
| }); | |
| const e = await entityItemRefetch(); | |
| if (e.data && onUpdateSuccess) { | |
| - await onUpdateSuccess(e.data); | |
| + onUpdateSuccess(e.data); | |
| } | |
| void queryClient.invalidateQueries({ | |
| queryKey: queryKey, | |
| diff --git a/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx b/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx | |
| index de854558..3a181153 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx | |
| @@ -61,7 +61,7 @@ const InteractiveWrapper = (args: StoryArgs) => { | |
| action("setHouseAccountId")(id); | |
| }} | |
| setHouseAccountAmount={(amt) => { | |
| - setAmount(+amt); | |
| + setAmount(amt); | |
| action("setHouseAccountAmount")(amt); | |
| }} | |
| setAmountChargeable={(balance) => { | |
| diff --git a/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.tsx b/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.tsx | |
| index e790ac22..36688344 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.tsx | |
| @@ -10,7 +10,7 @@ import { | |
| export type PayWithHouseAccountProps = { | |
| loyaltyCustomerId: number; | |
| setHouseAccountId: (houseAccountId: string) => void; | |
| - setHouseAccountAmount: (houseAccountAmount: string) => void; | |
| + setHouseAccountAmount: (houseAccountAmount: number) => void; | |
| setAmountChargeable?: (currentBalance: number | null) => void; | |
| houseAccountId?: string; | |
| amount: number; | |
| @@ -94,32 +94,21 @@ export const PayWithHouseAccount = ({ | |
| value={amount} | |
| type="number" | |
| step={0.01} | |
| - max={ | |
| - Math.min(maxAmount ?? Infinity, amountChargeable ?? Infinity) + | |
| - 0.01 | |
| - } | |
| + max={Math.min(maxAmount ?? Infinity, amountChargeable ?? Infinity)} | |
| onChange={(e) => { | |
| if (e.target.value === "") { | |
| - setHouseAccountAmount("0.00"); | |
| + setHouseAccountAmount(0); | |
| } else { | |
| - setHouseAccountAmount(e.target.value); | |
| + setHouseAccountAmount(+e.target.value); | |
| } | |
| }} | |
| /> | |
| )} | |
| {maxAmount && amountChargeable && !isPayingHouseAccount && ( | |
| <Button | |
| - type="button" | |
| - disabled={ | |
| - maxAmount.toFixed(2) == "0.00" || | |
| - maxAmount < 0 || | |
| - +amount > 0 || | |
| - isDisabled | |
| - } | |
| + disabled={amount === maxAmount || isDisabled} | |
| onClick={() => { | |
| - setHouseAccountAmount( | |
| - Math.min(maxAmount, amountChargeable).toFixed(2), | |
| - ); | |
| + setHouseAccountAmount(Math.min(maxAmount, amountChargeable)); | |
| }} | |
| > | |
| Max | |
| diff --git a/src/components/SalesScreenComponents/SalePageConfigProvider.tsx b/src/components/SalesScreenComponents/SalePageConfigProvider.tsx | |
| index ebbc9ff0..06d11c34 100644 | |
| --- a/src/components/SalesScreenComponents/SalePageConfigProvider.tsx | |
| +++ b/src/components/SalesScreenComponents/SalePageConfigProvider.tsx | |
| @@ -11,11 +11,8 @@ import { | |
| } from "src/spring-generated"; | |
| import { SalePageConfigDispatch, store } from "src/store/salePageConfig"; | |
| import { | |
| - overriddenCohortPriceLevelSelector, | |
| - resetOverriddenCohortPriceLevel, | |
| resetSalesChannel, | |
| selectedSalesChannelSelector, | |
| - selectOverriddenCohortPriceLevel, | |
| selectSalesChannel, | |
| setInStoreSalesChannel, | |
| } from "src/store/salePageConfig/salePageConfigSlice"; | |
| @@ -69,9 +66,6 @@ const SalePageConfigLoader: React.FC<{ children: React.ReactNode }> = ({ | |
| export const useSalePageConfig = () => { | |
| const dispatch = useDispatch<SalePageConfigDispatch>(); | |
| const selectedSalesChannel = useSelector(selectedSalesChannelSelector); | |
| - const overriddenCohortPriceLevel = useSelector( | |
| - overriddenCohortPriceLevelSelector, | |
| - ); | |
| const queryClient = useQueryClient(); | |
| if (!selectedSalesChannel) { | |
| @@ -96,23 +90,9 @@ export const useSalePageConfig = () => { | |
| dispatch(resetSalesChannel()); | |
| }, [dispatch]); | |
| - const selectOverriddenCohortPriceLevelCallback = useCallback( | |
| - (priceLevelId: number | undefined) => { | |
| - dispatch(selectOverriddenCohortPriceLevel(priceLevelId)); | |
| - }, | |
| - [dispatch], | |
| - ); | |
| - | |
| - const resetOverriddenCohortPriceLevelCallback = useCallback(() => { | |
| - dispatch(resetOverriddenCohortPriceLevel()); | |
| - }, [dispatch]); | |
| - | |
| return { | |
| selectedSalesChannel, | |
| selectSalesChannel: selectSalesChannelCallback, | |
| resetSalesChannel: resetSalesChannelCallback, | |
| - overriddenCohortPriceLevel, | |
| - selectOverriddenCohortPriceLevel: selectOverriddenCohortPriceLevelCallback, | |
| - resetOverriddenCohortPriceLevel: resetOverriddenCohortPriceLevelCallback, | |
| }; | |
| }; | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/CashOptions/CashOptions.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/CashOptions/CashOptions.tsx | |
| index 5b4082a9..7936485f 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/CashOptions/CashOptions.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/CashOptions/CashOptions.tsx | |
| @@ -1,12 +1,9 @@ | |
| import { isNotInStoreChannel } from "components/payment/disablePaymentMethods"; | |
| import { ButtonSize } from "components/ui/button"; | |
| -import { Tabs, TabsContent, TabsList, TabsTrigger } from "components/ui/tabs"; | |
| import { shadcnResponsiveButtonSizes } from "config/styles/button"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| import { TransactionPaymentForm } from "generated/types"; | |
| -import { useCallback, useEffect, useState } from "react"; | |
| -import { formatPrice } from "utils/currencyUtils"; | |
| import { SalesButtonGroup } from "../SalesButtonGroup"; | |
| export interface CashOptionsProps { | |
| @@ -29,188 +26,67 @@ export const CashOptions: React.FC<CashOptionsProps> = ({ | |
| isPersisting, | |
| isCalculatingCartPrice, | |
| salesChannel, | |
| - setSelectedCashPaymentMethodId, | |
| - calculateMethodsWithPrices, | |
| } = useSalesPaymentContext(); | |
| - | |
| const notInStoreChannel = isNotInStoreChannel({ | |
| salesChannelTypeId: salesChannel.salesChannelTypeId, | |
| cohortId: entity.cohortId, | |
| }); | |
| - | |
| - // Get deduplicated cash methods | |
| - const methodsWithPrices = calculateMethodsWithPrices( | |
| - TransactionPaymentForm.CASH, | |
| - ); | |
| - const cashMethods = methodsWithPrices.map(({ method }) => method); | |
| - | |
| - // State for selected cash method | |
| - const [selectedCashMethod, setSelectedCashMethod] = useState< | |
| - string | undefined | |
| - >(cashMethods.length > 0 ? cashMethods[0]?.id : undefined); | |
| - | |
| - // Get cash total for the selected method | |
| - // If no methods available (fallback context), use default total | |
| - const cashTotal = | |
| - methodsWithPrices.length > 0 | |
| - ? transactionTotalPrice({ paymentMethodId: selectedCashMethod }) | |
| - : transactionTotalPrice(); | |
| - | |
| - // Update the global payment method ID when the selected tab changes | |
| - useEffect(() => { | |
| - if ( | |
| - selectedCashMethod && | |
| - amountReceived?.paymentForm === TransactionPaymentForm.CASH | |
| - ) { | |
| - setAmountPaid((prev) => { | |
| - if (!prev) return prev; | |
| - return { | |
| - ...prev, | |
| - paymentMethodId: selectedCashMethod, | |
| - }; | |
| - }); | |
| - } | |
| - }, [selectedCashMethod, amountReceived?.paymentForm, setAmountPaid]); | |
| - | |
| - // Helper function to create money denomination buttons for a specific method | |
| - const createMoneyButtons = useCallback( | |
| - ( | |
| - methodId: string | undefined, | |
| - methodTotal: number, | |
| - testIdPrefix: string = "", | |
| - ) => { | |
| - return [ | |
| - "$5", | |
| - "$10", | |
| - "$20", | |
| - "$25", | |
| - "$50", | |
| - "$100", | |
| - `$${(methodTotal - (amountReceived?.amountPaid ?? 0)).toFixed(2)}`, | |
| - `$${Math.ceil(methodTotal - (amountReceived?.amountPaid ?? 0)).toFixed(2)}`, | |
| - ].map((money, i) => ({ | |
| - size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| - disabled: | |
| - !transactionItems.length || | |
| - transactionTotalPrice() < 0 || | |
| - isPersisting || | |
| - isCalculatingCartPrice || | |
| - notInStoreChannel, | |
| - requires: "payment_option/cash:use", | |
| - "data-testid": `moneys-${testIdPrefix}${i}`, | |
| - onClick: () => { | |
| - setAmountPaid((prev) => { | |
| - const newAmountPaid = | |
| - (prev?.amountPaid ?? 0) + +money.replaceAll("$", ""); | |
| - return { | |
| - ...prev, | |
| - amountPaid: newAmountPaid, | |
| - paymentForm: TransactionPaymentForm.CASH, | |
| - paymentMethodId: methodId || prev?.paymentMethodId, | |
| - }; | |
| - }); | |
| - }, | |
| - label: money, | |
| - })); | |
| - }, | |
| - [ | |
| - buttonSize, | |
| - transactionItems.length, | |
| - transactionTotalPrice, | |
| - isPersisting, | |
| - isCalculatingCartPrice, | |
| - notInStoreChannel, | |
| - amountReceived?.amountPaid, | |
| - setAmountPaid, | |
| - ], | |
| - ); | |
| - | |
| - if (cashTotal === undefined) { | |
| - return null; | |
| - } | |
| - | |
| - // Helper function to create the "Enter $" button | |
| - const createEnterButton = (methodId?: string) => ({ | |
| - label: "Enter $ (F2)", | |
| - requires: "payment_option/cash:use", | |
| - disabled: | |
| - !transactionItems.length || | |
| - isPersisting || | |
| - isCalculatingCartPrice || | |
| - notInStoreChannel, | |
| - onClick: () => { | |
| - setSelectedCashPaymentMethodId(methodId); | |
| - openPaymentModal(); | |
| - }, | |
| - size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| - "data-testid": `enter-custom-amount-btn${methodId ? `-${methodId}` : ""}`, | |
| + const MONEYS = [ | |
| + "$5", | |
| + "$10", | |
| + "$20", | |
| + "$25", | |
| + "$50", | |
| + "$100", | |
| + `$${(transactionTotalPrice() - (amountReceived?.amountPaid ?? 0)).toFixed(2)}`, | |
| + `$${Math.ceil(transactionTotalPrice() - (amountReceived?.amountPaid ?? 0)).toFixed(2)}`, | |
| + ].map((money, i) => { | |
| + return { | |
| + size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| + disabled: | |
| + !transactionItems.length || | |
| + transactionTotalPrice() < 0 || | |
| + isPersisting || | |
| + isCalculatingCartPrice || | |
| + notInStoreChannel, | |
| + requires: "payment_option/cash:use", | |
| + "data-testid": `moneys-${i}`, | |
| + onClick: () => { | |
| + setAmountPaid((prev) => { | |
| + const newAmountPaid = | |
| + (prev?.amountPaid ?? 0) + +money.replaceAll("$", ""); | |
| + return { | |
| + ...prev, | |
| + amountPaid: newAmountPaid, | |
| + paymentForm: TransactionPaymentForm.CASH, | |
| + }; | |
| + }); | |
| + }, | |
| + label: money, | |
| + }; | |
| }); | |
| - // Helper function to render cash content for a method | |
| - const renderCashContent = ( | |
| - methodId: string | undefined, | |
| - methodTotal: number, | |
| - testIdPrefix: string = "", | |
| - ) => ( | |
| - <> | |
| - <div className="text-lg font-semibold text-green-700 mb-3 text-center"> | |
| - Cash Total: {formatPrice(methodTotal)} | |
| - </div> | |
| - <SalesButtonGroup | |
| - colorScheme="green" | |
| - wrapProps={{ justifyContent: justifyButtons }} | |
| - elements={[ | |
| - ...createMoneyButtons(methodId, methodTotal, testIdPrefix), | |
| - createEnterButton(methodId), | |
| - ]} | |
| - /> | |
| - </> | |
| - ); | |
| - | |
| - // If no total, return null | |
| - if (cashTotal === undefined) { | |
| - return null; | |
| - } | |
| - | |
| - // If no cash methods (fallback context), show simple version with default total | |
| - if (methodsWithPrices.length === 0) { | |
| - return renderCashContent(undefined, cashTotal); | |
| - } | |
| - | |
| - // If only one cash method, show the simple version without tabs | |
| - if (methodsWithPrices.length === 1) { | |
| - return renderCashContent(selectedCashMethod, cashTotal); | |
| - } | |
| - | |
| - // Multiple cash methods - show tabs | |
| return ( | |
| - <Tabs | |
| - value={selectedCashMethod} | |
| - onValueChange={setSelectedCashMethod} | |
| - className="w-full" | |
| - > | |
| - <TabsList | |
| - className="grid w-full mb-4" | |
| - style={{ | |
| - gridTemplateColumns: `repeat(${methodsWithPrices.length}, 1fr)`, | |
| - }} | |
| - > | |
| - {methodsWithPrices.map(({ method, total }) => { | |
| - return ( | |
| - <TabsTrigger key={method.id} value={method.id} className="text-sm"> | |
| - {method.paymentMethodType} ({formatPrice(total || 0)}) | |
| - </TabsTrigger> | |
| - ); | |
| - })} | |
| - </TabsList> | |
| - | |
| - {methodsWithPrices.map(({ method, total }) => { | |
| - return ( | |
| - <TabsContent key={method.id} value={method.id} className="mt-0"> | |
| - {renderCashContent(method.id, total || 0, `${method.id}-`)} | |
| - </TabsContent> | |
| - ); | |
| - })} | |
| - </Tabs> | |
| + <SalesButtonGroup | |
| + colorScheme="green" | |
| + wrapProps={{ justifyContent: justifyButtons }} | |
| + elements={[ | |
| + ...MONEYS, | |
| + { | |
| + label: "Enter $ (F2)", | |
| + requires: "payment_option/cash:use", | |
| + disabled: | |
| + !transactionItems.length || | |
| + isPersisting || | |
| + isCalculatingCartPrice || | |
| + notInStoreChannel, | |
| + onClick: () => { | |
| + openPaymentModal(); | |
| + }, | |
| + size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| + "data-testid": "enter-custom-amount-btn", | |
| + }, | |
| + ]} | |
| + /> | |
| ); | |
| }; | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/Miscellaneous/Miscellaneous.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/Miscellaneous/Miscellaneous.tsx | |
| index 79d3c368..4c6b8d3f 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/Miscellaneous/Miscellaneous.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/Miscellaneous/Miscellaneous.tsx | |
| @@ -1,23 +1,23 @@ | |
| import { CheckCircleIcon, DeleteIcon } from "@chakra-ui/icons"; | |
| import { | |
| - FormControl, | |
| - FormLabel, | |
| - HStack, | |
| - Text, | |
| - useDisclosure, | |
| - useToast, | |
| + FormControl, | |
| + FormLabel, | |
| + HStack, | |
| + Text, | |
| + useDisclosure, | |
| + useToast, | |
| } from "@chakra-ui/react"; | |
| import PayoutModal from "components/payout/PayoutModal"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| import { | |
| - responsiveButtonSizes, | |
| - shadcnResponsiveButtonSizes, | |
| + responsiveButtonSizes, | |
| + shadcnResponsiveButtonSizes, | |
| } from "config/styles/button"; | |
| import { useAuthorization } from "context/AuthorizationContext/useAuthorizationContext"; | |
| import { useSalesContext } from "context/Sales/SalesContext"; | |
| import { | |
| - customerDiscount, | |
| - customerTaxExempt, | |
| + customerDiscount, | |
| + customerTaxExempt, | |
| } from "context/Sales/SalesContextProvider"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| import { format } from "date-fns"; | |
| @@ -29,15 +29,15 @@ import { FaPeopleGroup } from "react-icons/fa6"; | |
| import { MdDiscount, MdOutlinePayments } from "react-icons/md"; | |
| import { CustomerLookupModal } from "src/components/loyalty/CustomerLookupModal/CustomerLookupModal"; | |
| import { | |
| - useEntitySelected, | |
| - useLoyaltyProgramIdOptional, | |
| + useEntitySelected, | |
| + useLoyaltyProgramIdOptional, | |
| } from "src/context/EntityProvider"; | |
| import { | |
| - CartDiscountType, | |
| - LoyaltyCustomer, | |
| - LoyaltyCustomerProfile, | |
| - PaymentProcessorType, | |
| - useCancelTransaction, | |
| + CartDiscountType, | |
| + LoyaltyCustomer, | |
| + LoyaltyCustomerProfile, | |
| + PaymentProcessorType, | |
| + useCancelTransaction, | |
| } from "src/generated"; | |
| import { TransformitySwitch } from "../../../common/Switch/TransformitySwitch"; | |
| import { CartHoldsModal } from "../../Modals/CartHoldsModal"; | |
| @@ -47,32 +47,32 @@ import { SalesButtonGroup, SalesButtonGroupElement } from "../SalesButtonGroup"; | |
| export interface MiscellaneousProps {} | |
| export const Miscellaneous: React.FC<MiscellaneousProps> = () => { | |
| - const toast = useToast(); | |
| - const { | |
| - discount, | |
| - customer, | |
| - items: itemDetails = new Map<number, LineItem>(), | |
| - taxExempt, | |
| - setDeviceBusy, | |
| - selectedItems, | |
| - transactionId, | |
| - setTransactionId, | |
| - clearCart, | |
| - calculateCartPrice, | |
| - } = useSalesContext(); | |
| - const { overrideLogout } = useAuthorization(); | |
| - const { governmentID, customerLookupModal } = useSalesPaymentContext(); | |
| - const { id } = useLoyaltyProgramIdOptional(); | |
| - const [entity] = useEntitySelected(); | |
| - const [action, setAction] = useState("PAYOUT"); | |
| + const toast = useToast(); | |
| + const { | |
| + discount, | |
| + customer, | |
| + items: itemDetails = new Map<number, LineItem>(), | |
| + taxExempt, | |
| + setDeviceBusy, | |
| + selectedItems, | |
| + transactionId, | |
| + setTransactionId, | |
| + clearCart, | |
| + calculateCartPrice, | |
| + } = useSalesContext(); | |
| + const { overrideLogout } = useAuthorization(); | |
| + const { governmentID, customerLookupModal } = useSalesPaymentContext(); | |
| + const { id } = useLoyaltyProgramIdOptional(); | |
| + const [entity] = useEntitySelected(); | |
| + const [action, setAction] = useState("PAYOUT"); | |
| - // discount should be updated after modal is closed | |
| - const { isOpen, onOpen, onClose } = useDisclosure(); | |
| - const cartHoldsDisclosure = useDisclosure(); | |
| - const payoutDisclosure = useDisclosure(); | |
| - const { mutateAsync: cancelTransaction, isPending } = useCancelTransaction( | |
| - transactionId ?? 0, | |
| - ); | |
| + // discount should be updated after modal is closed | |
| + const { isOpen, onOpen, onClose } = useDisclosure(); | |
| + const cartHoldsDisclosure = useDisclosure(); | |
| + const payoutDisclosure = useDisclosure(); | |
| + const { mutateAsync: cancelTransaction, isPending } = useCancelTransaction( | |
| + transactionId ?? 0, | |
| + ); | |
| const elements: SalesButtonGroupElement[] = useMemo(() => { | |
| const discountPermission = | |
| @@ -194,170 +194,167 @@ export const Miscellaneous: React.FC<MiscellaneousProps> = () => { | |
| calculateCartPrice, | |
| ]); | |
| - const applyCustomerDiscountsToCart = async ( | |
| - customer: LoyaltyCustomer | LoyaltyCustomerProfile, | |
| - ) => { | |
| - // Convert LoyaltyCustomerProfile to LoyaltyCustomer format for cart calculations if needed | |
| - const customerForCart: LoyaltyCustomer = | |
| - "loyaltyCustomerId" in customer | |
| - ? { | |
| - ...customer, | |
| - id: customer.id, | |
| - loyaltyCustomerId: customer.loyaltyCustomerId, | |
| - customerId: customer.customerId, | |
| - isEmployee: customer.isEmployee ?? false, | |
| - } | |
| - : customer; | |
| + const applyCustomerDiscountsToCart = async ( | |
| + customer: LoyaltyCustomer | LoyaltyCustomerProfile, | |
| + ) => { | |
| + // Convert LoyaltyCustomerProfile to LoyaltyCustomer format for cart calculations if needed | |
| + const customerForCart: LoyaltyCustomer = | |
| + "loyaltyCustomerId" in customer | |
| + ? { | |
| + ...customer, | |
| + id: customer.id, | |
| + loyaltyCustomerId: customer.loyaltyCustomerId, | |
| + customerId: customer.customerId, | |
| + isEmployee: customer.isEmployee ?? false, | |
| + } | |
| + : customer; | |
| - try { | |
| - await calculateCartPrice({ | |
| - requestedItems: new Map( | |
| - [...itemDetails.entries()].map(([id, prevItem]) => { | |
| - const isPriceAtCost = customerForCart?.priceAtCost; | |
| - if (isPriceAtCost) { | |
| - const cost = prevItem.item?.ei_cost | |
| - ? Number(prevItem.item.ei_cost) | |
| - : undefined; | |
| - prevItem.price = cost ?? prevItem.price; | |
| - } else if (isNil(isPriceAtCost)) { | |
| - prevItem.price = prevItem.originalPrice ?? prevItem.price; | |
| - } | |
| + try { | |
| + await calculateCartPrice({ | |
| + requestedItems: new Map( | |
| + [...itemDetails.entries()].map(([id, prevItem]) => { | |
| + const isPriceAtCost = customerForCart?.priceAtCost; | |
| + if (isPriceAtCost) { | |
| + prevItem.price = prevItem.item?.cost ?? prevItem.price; | |
| + } else if (isNil(isPriceAtCost)) { | |
| + prevItem.price = prevItem.originalPrice ?? prevItem.price; | |
| + } | |
| - const lineItemDiscount = customerForCart?.lineItemFixedDiscount; | |
| - const lineItemDiscountPercent = lineItemDiscount | |
| - ? lineItemDiscount * 100 | |
| - : undefined; | |
| - prevItem.lineItemDiscount = lineItemDiscountPercent | |
| - ? { | |
| - type: CartDiscountType.PERCENT, | |
| - value: lineItemDiscountPercent, | |
| - } | |
| - : undefined; | |
| + const lineItemDiscount = customerForCart?.lineItemFixedDiscount; | |
| + const lineItemDiscountPercent = lineItemDiscount | |
| + ? lineItemDiscount * 100 | |
| + : undefined; | |
| + prevItem.lineItemDiscount = lineItemDiscountPercent | |
| + ? { | |
| + type: CartDiscountType.PERCENT, | |
| + value: lineItemDiscountPercent, | |
| + } | |
| + : undefined; | |
| - return [id, prevItem]; | |
| - }), | |
| - ), | |
| - requestedCustomer: customerForCart, | |
| - requestTaxExempt: customerTaxExempt(customerForCart), | |
| - requestedDiscount: !customerForCart?.lineItemFixedDiscount | |
| - ? customerDiscount(customerForCart) | |
| - : undefined, | |
| - }); | |
| - } catch { | |
| - // no need to do anything since the error is handled in calculateCartPrice | |
| - } | |
| - }; | |
| + return [id, prevItem]; | |
| + }), | |
| + ), | |
| + requestedCustomer: customerForCart, | |
| + requestTaxExempt: customerTaxExempt(customerForCart), | |
| + requestedDiscount: !customerForCart?.lineItemFixedDiscount | |
| + ? customerDiscount(customerForCart) | |
| + : undefined, | |
| + }); | |
| + } catch { | |
| + // no need to do anything since the error is handled in calculateCartPrice | |
| + } | |
| + }; | |
| - const updateCartWithCustomerDiscounts = async ( | |
| - updatedCustomer: LoyaltyCustomerProfile, | |
| - ) => { | |
| - await applyCustomerDiscountsToCart(updatedCustomer); | |
| - }; | |
| + const updateCartWithCustomerDiscounts = async ( | |
| + updatedCustomer: LoyaltyCustomerProfile, | |
| + ) => { | |
| + await applyCustomerDiscountsToCart(updatedCustomer); | |
| + }; | |
| - return ( | |
| - <> | |
| - <SalesButtonGroup | |
| - elements={elements} | |
| - colorScheme="red" | |
| - wrapItemProps={{ alignItems: "center" }} | |
| - /> | |
| - <DiscountModal | |
| - isOpen={isOpen} | |
| - onClose={onClose} | |
| - setDiscountValue={async (discountVal) => { | |
| - if (selectedItems.size > 0) { | |
| - try { | |
| - await calculateCartPrice({ | |
| - requestedItems: new Map( | |
| - [...itemDetails.values()].map((prevItem) => { | |
| - if (selectedItems.has(prevItem.id)) { | |
| - prevItem.lineItemDiscount = discountVal; | |
| - } | |
| - return [prevItem.id, prevItem]; | |
| - }), | |
| - ), | |
| - requestedCustomer: customer, | |
| - requestTaxExempt: taxExempt, | |
| - requestedDiscount: discount, | |
| - }); | |
| - } catch (e) { | |
| - // no need to do anything since the error is handled in calculateCartPrice | |
| - } | |
| - } else { | |
| - try { | |
| - await calculateCartPrice({ | |
| - requestedItems: itemDetails, | |
| - requestedCustomer: customer, | |
| - requestTaxExempt: taxExempt, | |
| - requestedDiscount: discountVal, | |
| - }); | |
| - } catch (e) { | |
| - // no need to do anything since the error is handled in calculateCartPrice | |
| - } | |
| - } | |
| - }} | |
| - discountValue={discount} | |
| - /> | |
| - <CartHoldsModal | |
| - isOpen={cartHoldsDisclosure.isOpen} | |
| - onClose={cartHoldsDisclosure.onClose} | |
| - /> | |
| - <CustomerLookupModal | |
| - defaultValues={ | |
| - governmentID | |
| - ? { | |
| - birthDate: governmentID.birthdate | |
| - ? format(governmentID.birthdate, "MMddyyyy") | |
| - : undefined, | |
| - ...governmentID, | |
| - } | |
| - : undefined | |
| - } | |
| - disclosure={customerLookupModal} | |
| - setCustomer={async (customer) => { | |
| - if (customer) { | |
| - await applyCustomerDiscountsToCart(customer); | |
| - } else { | |
| - // When customer is undefined (unlinked), recalculate cart without customer discounts | |
| - try { | |
| - await calculateCartPrice({ | |
| - requestedItems: new Map( | |
| - [...itemDetails.entries()].map(([id, prevItem]) => { | |
| - // Reset to original price when customer is unlinked | |
| - prevItem.price = prevItem.originalPrice ?? prevItem.price; | |
| - // Remove line item discounts | |
| - prevItem.lineItemDiscount = undefined; | |
| - return [id, prevItem]; | |
| - }), | |
| - ), | |
| - requestedCustomer: undefined, | |
| - requestTaxExempt: false, | |
| - requestedDiscount: undefined, | |
| - }); | |
| - } catch { | |
| - // no need to do anything since the error is handled in calculateCartPrice | |
| - } | |
| - } | |
| - }} | |
| - linkedCustomer={customer} | |
| - onCustomerUpdated={updateCartWithCustomerDiscounts} | |
| - allowDeviceActions={ | |
| - entity.paymentProcessor?.processorName === PaymentProcessorType.stripe | |
| - } | |
| - setDeviceBusy={setDeviceBusy} | |
| - /> | |
| - <PayoutModal | |
| - {...payoutDisclosure} | |
| - onClose={() => { | |
| - setAction("PAYOUT"); | |
| - payoutDisclosure.onClose(); | |
| - }} | |
| - action={action} | |
| - setAction={setAction} | |
| - onSubmit={(data: any) => { | |
| - console.log(data); | |
| - }} | |
| - /> | |
| - </> | |
| - ); | |
| + return ( | |
| + <> | |
| + <SalesButtonGroup | |
| + elements={elements} | |
| + colorScheme="red" | |
| + wrapItemProps={{ alignItems: "center" }} | |
| + /> | |
| + <DiscountModal | |
| + isOpen={isOpen} | |
| + onClose={onClose} | |
| + setDiscountValue={async (discountVal) => { | |
| + if (selectedItems.size > 0) { | |
| + try { | |
| + await calculateCartPrice({ | |
| + requestedItems: new Map( | |
| + [...itemDetails.values()].map((prevItem) => { | |
| + if (selectedItems.has(prevItem.id)) { | |
| + prevItem.lineItemDiscount = discountVal; | |
| + } | |
| + return [prevItem.id, prevItem]; | |
| + }), | |
| + ), | |
| + requestedCustomer: customer, | |
| + requestTaxExempt: taxExempt, | |
| + requestedDiscount: discount, | |
| + }); | |
| + } catch (e) { | |
| + // no need to do anything since the error is handled in calculateCartPrice | |
| + } | |
| + } else { | |
| + try { | |
| + await calculateCartPrice({ | |
| + requestedItems: itemDetails, | |
| + requestedCustomer: customer, | |
| + requestTaxExempt: taxExempt, | |
| + requestedDiscount: discountVal, | |
| + }); | |
| + } catch (e) { | |
| + // no need to do anything since the error is handled in calculateCartPrice | |
| + } | |
| + } | |
| + }} | |
| + discountValue={discount} | |
| + /> | |
| + <CartHoldsModal | |
| + isOpen={cartHoldsDisclosure.isOpen} | |
| + onClose={cartHoldsDisclosure.onClose} | |
| + /> | |
| + <CustomerLookupModal | |
| + defaultValues={ | |
| + governmentID | |
| + ? { | |
| + birthDate: governmentID.birthdate | |
| + ? format(governmentID.birthdate, "MMddyyyy") | |
| + : undefined, | |
| + ...governmentID, | |
| + } | |
| + : undefined | |
| + } | |
| + disclosure={customerLookupModal} | |
| + setCustomer={async (customer) => { | |
| + if (customer) { | |
| + await applyCustomerDiscountsToCart(customer); | |
| + } else { | |
| + // When customer is undefined (unlinked), recalculate cart without customer discounts | |
| + try { | |
| + await calculateCartPrice({ | |
| + requestedItems: new Map( | |
| + [...itemDetails.entries()].map(([id, prevItem]) => { | |
| + // Reset to original price when customer is unlinked | |
| + prevItem.price = prevItem.originalPrice ?? prevItem.price; | |
| + // Remove line item discounts | |
| + prevItem.lineItemDiscount = undefined; | |
| + return [id, prevItem]; | |
| + }), | |
| + ), | |
| + requestedCustomer: undefined, | |
| + requestTaxExempt: false, | |
| + requestedDiscount: undefined, | |
| + }); | |
| + } catch { | |
| + // no need to do anything since the error is handled in calculateCartPrice | |
| + } | |
| + } | |
| + }} | |
| + linkedCustomer={customer} | |
| + onCustomerUpdated={updateCartWithCustomerDiscounts} | |
| + allowDeviceActions={ | |
| + entity.paymentProcessor?.processorName === PaymentProcessorType.stripe | |
| + } | |
| + setDeviceBusy={setDeviceBusy} | |
| + /> | |
| + <PayoutModal | |
| + {...payoutDisclosure} | |
| + onClose={() => { | |
| + setAction("PAYOUT"); | |
| + payoutDisclosure.onClose(); | |
| + }} | |
| + action={action} | |
| + setAction={setAction} | |
| + onSubmit={(data: any) => { | |
| + console.log(data); | |
| + }} | |
| + /> | |
| + </> | |
| + ); | |
| }; | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/CreditCardOptions.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/CreditCardOptions.tsx | |
| deleted file mode 100644 | |
| index f3e97c66..00000000 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/CreditCardOptions.tsx | |
| +++ /dev/null | |
| @@ -1,108 +0,0 @@ | |
| -import { isNotInStoreChannel } from "components/payment/disablePaymentMethods"; | |
| -import { ButtonSize } from "components/ui/button"; | |
| -import { shadcnResponsiveButtonSizes } from "config/styles/button"; | |
| -import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| -import { TransactionPaymentForm } from "generated/types"; | |
| -import { FaCreditCard } from "react-icons/fa"; | |
| -import { useEntitySelected } from "src/context/EntityProvider"; | |
| -import { formatPrice } from "utils/currencyUtils"; | |
| -import { SalesButton } from "../SalesButtonGroup"; | |
| - | |
| -export interface CreditCardOptionsProps { | |
| - buttonSize?: ButtonSize | ButtonSize[]; | |
| - onSubmit?: () => void; | |
| -} | |
| - | |
| -export const CreditCardOptions = ({ | |
| - buttonSize, | |
| - onSubmit, | |
| -}: CreditCardOptionsProps): SalesButton[] => { | |
| - const [entity] = useEntitySelected(); | |
| - const { | |
| - transactionItems, | |
| - transactionTotalPrice, | |
| - creditCardPaid, | |
| - creditCardModalV2, | |
| - reviewTransactionModal, | |
| - isPersisting, | |
| - isCalculatingCartPrice, | |
| - salesChannel, | |
| - paymentMethodTypeToPaymentMethod, | |
| - calculateMethodsWithPrices, | |
| - } = useSalesPaymentContext(); | |
| - | |
| - const notInStoreChannel = isNotInStoreChannel({ | |
| - salesChannelTypeId: salesChannel.salesChannelTypeId, | |
| - cohortId: entity.cohortId, | |
| - }); | |
| - const creditCardMethods = | |
| - paymentMethodTypeToPaymentMethod[TransactionPaymentForm["CREDIT CARD"]] || | |
| - []; | |
| - | |
| - const handleCreditCardClick = | |
| - (paymentMethodId?: string) => (e: React.MouseEvent) => { | |
| - e.preventDefault(); | |
| - e.stopPropagation(); | |
| - (e.currentTarget as HTMLButtonElement).blur(); | |
| - creditCardPaid(undefined, paymentMethodId); | |
| - creditCardModalV2.onOpen(); | |
| - reviewTransactionModal.onClose(); | |
| - onSubmit?.(); | |
| - }; | |
| - | |
| - // Create buttons for each credit card method, deduplicating by total price | |
| - const methodsWithPrices = calculateMethodsWithPrices( | |
| - TransactionPaymentForm["CREDIT CARD"], | |
| - ); | |
| - const creditCardButtons: SalesButton[] = methodsWithPrices.map( | |
| - ({ method, total }) => { | |
| - const label = `Credit (${formatPrice(total)})`; | |
| - | |
| - const isDisabled = | |
| - !transactionItems.length || | |
| - !entity.creditCardMerchantId || | |
| - isPersisting || | |
| - total === undefined || | |
| - total <= 0 || | |
| - isCalculatingCartPrice || | |
| - notInStoreChannel; | |
| - | |
| - return { | |
| - label, | |
| - leftIcon: <FaCreditCard />, | |
| - requires: "payment_option/credit_card:use", | |
| - size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| - disabled: isDisabled, | |
| - onClick: handleCreditCardClick(method.id), | |
| - } as SalesButton; | |
| - }, | |
| - ); | |
| - | |
| - // If no specific methods, return the default credit card button | |
| - if (creditCardButtons.length === 0) { | |
| - const defaultTotal = transactionTotalPrice(); | |
| - const defaultLabel = `Credit (F8) (${formatPrice(defaultTotal)})`; | |
| - | |
| - const isDisabled = | |
| - !transactionItems.length || | |
| - !entity.creditCardMerchantId || | |
| - isPersisting || | |
| - defaultTotal === undefined || | |
| - defaultTotal <= 0 || | |
| - isCalculatingCartPrice || | |
| - notInStoreChannel; | |
| - | |
| - return [ | |
| - { | |
| - label: defaultLabel, | |
| - leftIcon: <FaCreditCard />, | |
| - requires: "payment_option/credit_card:use", | |
| - size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| - disabled: isDisabled, | |
| - onClick: handleCreditCardClick(), | |
| - } as SalesButton, | |
| - ]; | |
| - } | |
| - | |
| - return creditCardButtons; | |
| -}; | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/GiftCards/GiftCardSaleModal.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/GiftCards/GiftCardSaleModal.tsx | |
| index d9041b9a..e70b6711 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/GiftCards/GiftCardSaleModal.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/GiftCards/GiftCardSaleModal.tsx | |
| @@ -30,7 +30,6 @@ export type GiftCardSaleModalProps = { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| onClick: (giftCard: GiftCardSaleFormProps) => void; | |
| - paymentMethodId?: string; | |
| }; | |
| export function currGiftCardBalance(currGiftCard?: GiftCard | null) { | |
| @@ -50,7 +49,6 @@ export const GiftCardSaleModal = ({ | |
| isOpen, | |
| onClose, | |
| onClick, | |
| - paymentMethodId, | |
| }: GiftCardSaleModalProps) => { | |
| const { | |
| handleSubmit, | |
| @@ -138,8 +136,7 @@ export const GiftCardSaleModal = ({ | |
| isDisabled={ | |
| isValid && | |
| (currGiftCard?.balance ?? 0) !== 0 && | |
| - (currGiftCard?.balance ?? 0) > | |
| - transactionTotalPrice({ paymentMethodId }) | |
| + (currGiftCard?.balance ?? 0) > transactionTotalPrice() | |
| } | |
| label={ | |
| "Gift Card is not valid or does not have sufficient balance." | |
| @@ -151,8 +148,7 @@ export const GiftCardSaleModal = ({ | |
| isDisabled={ | |
| !isValid || | |
| (currGiftCard?.balance ?? 0) === 0 || | |
| - (currGiftCard?.balance ?? 0) < | |
| - transactionTotalPrice({ paymentMethodId }) | |
| + (currGiftCard?.balance ?? 0) < transactionTotalPrice() | |
| } | |
| type="submit" | |
| > | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/HouseAccountPaymentModal.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/HouseAccountPaymentModal.tsx | |
| index f3878d30..95d0401d 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/HouseAccountPaymentModal.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/HouseAccountPaymentModal.tsx | |
| @@ -10,12 +10,11 @@ import { CustomerEditModal } from "../../../../loyalty/CustomerProfile/CustomerE | |
| type HouseAccountPaymentModalProps = { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| - paymentMethodId?: string; | |
| }; | |
| export const HouseAccountPaymentModal: React.FC< | |
| HouseAccountPaymentModalProps | |
| -> = ({ isOpen, onClose, paymentMethodId }) => { | |
| +> = ({ isOpen, onClose }) => { | |
| const { | |
| customer, | |
| setAmountPaid, | |
| @@ -52,14 +51,11 @@ export const HouseAccountPaymentModal: React.FC< | |
| amountPaid: 0, | |
| houseAccountId, | |
| paymentForm: TransactionPaymentForm["HOUSE ACCOUNT"], | |
| - paymentMethodId, | |
| })); | |
| }, | |
| - [setAmountPaid, paymentMethodId], | |
| + [setAmountPaid], | |
| ); | |
| - const houseAccountAmount = transactionTotalPrice({ paymentMethodId }); | |
| - | |
| return ( | |
| <> | |
| <BasicModal | |
| @@ -84,19 +80,18 @@ export const HouseAccountPaymentModal: React.FC< | |
| })) | |
| } | |
| houseAccountId={amountReceived?.houseAccountId} | |
| - amount={houseAccountAmount} | |
| + amount={transactionTotalPrice()} | |
| showAmount={false} | |
| onTriggerCreateHouseAccount={handleTriggerCreateHouseAccount} | |
| /> | |
| <div className="flex flex-row justify-end gap-2"> | |
| <Button | |
| - disabled={houseAccountAmount > (amountChargeable ?? 0)} | |
| + disabled={transactionTotalPrice() > (amountChargeable ?? 0)} | |
| onClick={() => { | |
| setAmountPaid((prev) => ({ | |
| ...prev, | |
| paymentForm: TransactionPaymentForm["HOUSE ACCOUNT"], | |
| - paymentMethodId, | |
| - houseAccountAmount: houseAccountAmount, | |
| + houseAccountAmount: transactionTotalPrice(), | |
| amountPaid: 0, | |
| })); | |
| onClose(); | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.test.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.test.tsx | |
| deleted file mode 100644 | |
| index 2090633c..00000000 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.test.tsx | |
| +++ /dev/null | |
| @@ -1,376 +0,0 @@ | |
| -import { useDisclosure } from "@chakra-ui/react"; | |
| -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | |
| -import { fireEvent, render, screen } from "@testing-library/react"; | |
| -import { TransactionPaymentForm } from "src/generated"; | |
| -import { | |
| - createMockSalesContext, | |
| - createMockSalesPaymentContext, | |
| -} from "src/test-utils"; | |
| -import { MockEntityProvider } from "src/test/mocks/entityProvider"; | |
| -import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| -import { OtherOptionsModal, OtherOptionsModalType } from "./OtherOptionsModal"; | |
| - | |
| -// Create mocks using the consolidated functions | |
| -const mockSalesContext = createMockSalesContext({ | |
| - paymentMethodTypeToPaymentMethod: { | |
| - [TransactionPaymentForm.CASH]: [{ id: "cash-1", name: "Cash" }], | |
| - [TransactionPaymentForm["CREDIT CARD"]]: [ | |
| - { id: "cc-1", name: "Credit Card" }, | |
| - ], | |
| - [TransactionPaymentForm.CHECK]: [{ id: "check-1", name: "Check" }], | |
| - [TransactionPaymentForm["GIFT CARD"]]: [ | |
| - { id: "gift-1", name: "Gift Card" }, | |
| - ], | |
| - [TransactionPaymentForm.LATER]: [{ id: "later-1", name: "Pay Later" }], | |
| - [TransactionPaymentForm.OTHER]: [{ id: "other-1", name: "Other" }], | |
| - [TransactionPaymentForm.POINTS]: [{ id: "points-1", name: "Points" }], | |
| - [TransactionPaymentForm["HOUSE ACCOUNT"]]: [ | |
| - { id: "house-1", name: "House Account" }, | |
| - ], | |
| - }, | |
| -}); | |
| -const mockSalesPaymentContext = createMockSalesPaymentContext({ | |
| - salesChannel: { salesChannelTypeId: 1, defaultPaymentMethodId: "cash-1" }, // In-store channel | |
| -}); | |
| - | |
| -// Mock the SalesContext | |
| -vi.mock("src/context/Sales/SalesContext", () => ({ | |
| - useSalesContext: () => mockSalesContext, | |
| -})); | |
| - | |
| -// Mock the SalesPaymentContext | |
| -vi.mock("src/context/Sales/SalesPaymentContext", () => ({ | |
| - useSalesPaymentContext: () => mockSalesPaymentContext, | |
| -})); | |
| - | |
| -// Mock the ManualCardPunchModal | |
| -vi.mock( | |
| - "src/components/SalesScreenComponents/Modals/ManualCardPunchModal", | |
| - () => ({ | |
| - ManualCardPunchModal: ({ isOpen, onClose, onSubmit }: any) => ( | |
| - <div data-testid="manual-card-punch-modal"> | |
| - {isOpen && ( | |
| - <div> | |
| - <button onClick={onClose} data-testid="manual-modal-close"> | |
| - Close | |
| - </button> | |
| - <button onClick={onSubmit} data-testid="manual-modal-submit"> | |
| - Submit | |
| - </button> | |
| - </div> | |
| - )} | |
| - </div> | |
| - ), | |
| - }), | |
| -); | |
| - | |
| -// Test wrapper component | |
| -const TestWrapper = ({ children }: { children: React.ReactNode }) => { | |
| - const queryClient = new QueryClient({ | |
| - defaultOptions: { | |
| - queries: { retry: false }, | |
| - mutations: { retry: false }, | |
| - }, | |
| - }); | |
| - | |
| - return ( | |
| - <QueryClientProvider client={queryClient}> | |
| - <MockEntityProvider>{children}</MockEntityProvider> | |
| - </QueryClientProvider> | |
| - ); | |
| -}; | |
| - | |
| -// Helper component to test the modal | |
| -const TestOtherOptionsModal = (props: Partial<OtherOptionsModalType>) => { | |
| - const disclosure = useDisclosure({ isOpen: true }); | |
| - const giftCardDisclosure = useDisclosure(); | |
| - const houseAccountDisclosure = useDisclosure(); | |
| - | |
| - return ( | |
| - <OtherOptionsModal | |
| - disclosure={disclosure} | |
| - giftCardDisclosure={giftCardDisclosure} | |
| - houseAccountDisclosure={houseAccountDisclosure} | |
| - setSelectedHouseAccountPaymentMethodId={vi.fn()} | |
| - setSelectedGiftCardPaymentMethodId={vi.fn()} | |
| - {...props} | |
| - /> | |
| - ); | |
| -}; | |
| - | |
| -describe("OtherOptionsModal", () => { | |
| - beforeEach(() => { | |
| - vi.clearAllMocks(); | |
| - }); | |
| - | |
| - it("renders the modal with payment options", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - expect(screen.getByText("Payment Options")).toBeInTheDocument(); | |
| - expect(screen.getByText("Check")).toBeInTheDocument(); | |
| - expect(screen.getByText("Gift Card")).toBeInTheDocument(); | |
| - // Pay Later button may not be rendered if no payment methods are available | |
| - const payLaterButton = screen.queryByText("Pay Later"); | |
| - // If it exists, it should be in the document | |
| - if (payLaterButton) { | |
| - expect(payLaterButton).toBeInTheDocument(); | |
| - } | |
| - expect(screen.getByText("Manual Card")).toBeInTheDocument(); | |
| - expect(screen.getByText("Other/External")).toBeInTheDocument(); | |
| - // Points button may not be rendered if no payment methods are available | |
| - const pointsButton = screen.queryByText("Points"); | |
| - // If it exists, it should be in the document | |
| - if (pointsButton) { | |
| - expect(pointsButton).toBeInTheDocument(); | |
| - } | |
| - expect(screen.getByText("House Account")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("calls transactionTotalPrice when calculating payment amounts", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // The component should call transactionTotalPrice during rendering to determine button states | |
| - expect(mockSalesPaymentContext.transactionTotalPrice).toHaveBeenCalled(); | |
| - }); | |
| - | |
| - it("uses correct transaction total price for Check payment", () => { | |
| - // Set up a specific return value to test | |
| - mockSalesPaymentContext.transactionTotalPrice.mockReturnValue(40); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const checkButton = screen.getByText("Check"); | |
| - | |
| - // Only click if the button is not disabled | |
| - if (!checkButton.hasAttribute("disabled")) { | |
| - fireEvent.click(checkButton); | |
| - | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith({ | |
| - amountPaid: 0, | |
| - checkAmountReceived: 40, | |
| - paymentForm: TransactionPaymentForm.CHECK, | |
| - }); | |
| - } | |
| - }); | |
| - | |
| - it("uses correct transaction total price for Other payment", () => { | |
| - // Set up a specific return value to test | |
| - mockSalesPaymentContext.transactionTotalPrice.mockReturnValue(40); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const otherButton = screen.getByText("Other/External"); | |
| - | |
| - // Only click if the button is not disabled | |
| - if (!otherButton.hasAttribute("disabled")) { | |
| - fireEvent.click(otherButton); | |
| - | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith({ | |
| - amountPaid: 0, | |
| - otherAmountReceived: 40, | |
| - paymentForm: TransactionPaymentForm.OTHER, | |
| - }); | |
| - } | |
| - }); | |
| - | |
| - it("sets correct payment form for Pay Later", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const payLaterButton = screen.getByTestId("other-options-pay-later-btn"); | |
| - | |
| - // Only click if the button is not disabled | |
| - if (!payLaterButton.hasAttribute("disabled")) { | |
| - fireEvent.click(payLaterButton); | |
| - | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith({ | |
| - amountPaid: 0, | |
| - otherAmountReceived: 0, | |
| - checkAmountReceived: 0, | |
| - creditCardAmountReceived: 0, | |
| - paymentForm: TransactionPaymentForm.LATER, | |
| - }); | |
| - } | |
| - }); | |
| - | |
| - it("opens gift card modal when Gift Card is clicked", () => { | |
| - const giftCardDisclosure = { | |
| - onOpen: vi.fn(), | |
| - onClose: vi.fn(), | |
| - onToggle: vi.fn(), | |
| - isOpen: false, | |
| - isControlled: false, | |
| - getButtonProps: vi.fn(() => ({})), | |
| - getDisclosureProps: vi.fn(() => ({})), | |
| - }; | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal giftCardDisclosure={giftCardDisclosure} /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const giftCardButton = screen.getByText("Gift Card"); | |
| - | |
| - // Only click if the button is not disabled | |
| - if (!giftCardButton.hasAttribute("disabled")) { | |
| - fireEvent.click(giftCardButton); | |
| - expect(giftCardDisclosure.onOpen).toHaveBeenCalled(); | |
| - } | |
| - }); | |
| - | |
| - it("opens house account modal when House Account is clicked", () => { | |
| - const houseAccountDisclosure = { | |
| - onOpen: vi.fn(), | |
| - onClose: vi.fn(), | |
| - onToggle: vi.fn(), | |
| - isOpen: false, | |
| - isControlled: false, | |
| - getButtonProps: vi.fn(() => ({})), | |
| - getDisclosureProps: vi.fn(() => ({})), | |
| - }; | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal | |
| - houseAccountDisclosure={houseAccountDisclosure} | |
| - /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const houseAccountButton = screen.getByText("House Account"); | |
| - | |
| - // Only click if the button is not disabled | |
| - if (!houseAccountButton.hasAttribute("disabled")) { | |
| - fireEvent.click(houseAccountButton); | |
| - expect(houseAccountDisclosure.onOpen).toHaveBeenCalled(); | |
| - } | |
| - }); | |
| - | |
| - it("opens multiple payments modal when Points is clicked", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const pointsButton = screen.getByText("Points"); | |
| - | |
| - // Only click if the button is not disabled | |
| - if (!pointsButton.hasAttribute("disabled")) { | |
| - fireEvent.click(pointsButton); | |
| - expect( | |
| - mockSalesPaymentContext.multiplePaymentsModal.onOpen, | |
| - ).toHaveBeenCalled(); | |
| - } | |
| - }); | |
| - | |
| - it("verifies transactionTotalPrice is called for pricing calculations", () => { | |
| - // Test with a specific return value | |
| - const testValue = 40; | |
| - mockSalesPaymentContext.transactionTotalPrice.mockReturnValue(testValue); | |
| - | |
| - const { unmount } = render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Verify the function was called during component rendering | |
| - expect(mockSalesPaymentContext.transactionTotalPrice).toHaveBeenCalled(); | |
| - | |
| - // Test that the returned value would be used correctly if buttons are clicked | |
| - const checkButton = screen.getByText("Check"); | |
| - const otherButton = screen.getByText("Other/External"); | |
| - | |
| - if (!checkButton.hasAttribute("disabled")) { | |
| - fireEvent.click(checkButton); | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith( | |
| - expect.objectContaining({ | |
| - checkAmountReceived: testValue, | |
| - }), | |
| - ); | |
| - } | |
| - | |
| - vi.clearAllMocks(); | |
| - | |
| - if (!otherButton.hasAttribute("disabled")) { | |
| - fireEvent.click(otherButton); | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith( | |
| - expect.objectContaining({ | |
| - otherAmountReceived: testValue, | |
| - }), | |
| - ); | |
| - } | |
| - | |
| - unmount(); | |
| - }); | |
| - | |
| - it("handles transaction items correctly", () => { | |
| - // Test with transaction items present | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // All buttons should be present (whether enabled or disabled depends on other factors) | |
| - expect(screen.getByText("Check")).toBeInTheDocument(); | |
| - expect(screen.getByText("Gift Card")).toBeInTheDocument(); | |
| - // Pay Later button may not be rendered if no payment methods are available | |
| - const payLaterText = screen.queryByText("Pay Later"); | |
| - // If it exists, it should be in the document | |
| - if (payLaterText) { | |
| - expect(payLaterText).toBeInTheDocument(); | |
| - } | |
| - expect(screen.getByText("Manual Card")).toBeInTheDocument(); | |
| - expect(screen.getByText("Other/External")).toBeInTheDocument(); | |
| - // Points button may not be rendered if no payment methods are available | |
| - const pointsText = screen.queryByText("Points"); | |
| - // If it exists, it should be in the document | |
| - if (pointsText) { | |
| - expect(pointsText).toBeInTheDocument(); | |
| - } | |
| - expect(screen.getByText("House Account")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("displays correct payment form constants", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <TestOtherOptionsModal /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Test that the component uses the correct TransactionPaymentForm constants | |
| - const payLaterButton = screen.getByTestId("other-options-pay-later-btn"); | |
| - | |
| - if (!payLaterButton.hasAttribute("disabled")) { | |
| - fireEvent.click(payLaterButton); | |
| - | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith( | |
| - expect.objectContaining({ | |
| - paymentForm: TransactionPaymentForm.LATER, | |
| - }), | |
| - ); | |
| - } | |
| - }); | |
| -}); | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.tsx | |
| index 19a38787..270b2293 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/OtherOptionsModal.tsx | |
| @@ -4,36 +4,26 @@ import { | |
| isInStoreChannel, | |
| isNotInStoreChannel, | |
| } from "components/payment/disablePaymentMethods"; | |
| -import { | |
| - CreditCardPriceOption, | |
| - ManualCardPunchModal, | |
| -} from "components/SalesScreenComponents/Modals/ManualCardPunchModal"; | |
| +import { ManualCardPunchModal } from "components/SalesScreenComponents/Modals/ManualCardPunchModal"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| import { TransactionPaymentForm } from "generated/types"; | |
| -import { useMemo, useState } from "react"; | |
| +import { useMemo } from "react"; | |
| import { FaMoneyCheck } from "react-icons/fa"; | |
| -import { EntitySalesChannelPaymentMethod } from "src/spring-generated"; | |
| -import { formatPrice } from "utils/currencyUtils"; | |
| import { | |
| SalesButtonGroup, | |
| SalesButtonGroupElement, | |
| } from "../../SalesButtonGroup"; | |
| -import { PAYMENT_BUTTON_STYLES } from "./buttonStyles"; | |
| export type OtherOptionsModalType = { | |
| disclosure: UseDisclosureReturn; | |
| giftCardDisclosure: UseDisclosureReturn; | |
| houseAccountDisclosure: UseDisclosureReturn; | |
| - setSelectedHouseAccountPaymentMethodId: (id: string | undefined) => void; | |
| - setSelectedGiftCardPaymentMethodId: (id: string | undefined) => void; | |
| }; | |
| export const OtherOptionsModal = ({ | |
| disclosure, | |
| giftCardDisclosure, | |
| houseAccountDisclosure, | |
| - setSelectedHouseAccountPaymentMethodId, | |
| - setSelectedGiftCardPaymentMethodId, | |
| }: OtherOptionsModalType) => { | |
| const { | |
| transactionItems, | |
| @@ -44,17 +34,11 @@ export const OtherOptionsModal = ({ | |
| multiplePaymentsModal, | |
| salesChannel, | |
| salePaymentType, | |
| - paymentMethodTypeToPaymentMethod, | |
| - calculateMethodsWithPrices, | |
| } = useSalesPaymentContext(); | |
| const { onClose } = disclosure; | |
| const { onOpen: openGiftCardModal } = giftCardDisclosure; | |
| const manualPunchModal = useDisclosure({}); | |
| const [entity] = useEntitySelected(); | |
| - const [selectedCreditCardPrice, setSelectedCreditCardPrice] = useState< | |
| - CreditCardPriceOption | undefined | |
| - >(); | |
| - | |
| const elements: SalesButtonGroupElement[] = useMemo(() => { | |
| const inStoreChannel = isInStoreChannel({ | |
| salesChannelTypeId: salesChannel.salesChannelTypeId, | |
| @@ -64,189 +48,49 @@ export const OtherOptionsModal = ({ | |
| salesChannelTypeId: salesChannel.salesChannelTypeId, | |
| cohortId: entity.cohortId, | |
| }); | |
| - | |
| - const formatPriceWithCondition = ( | |
| - paymentMethodId?: string, | |
| - forceShowPrice: boolean = false, | |
| - ) => { | |
| - const total = transactionTotalPrice({ paymentMethodId }); | |
| - const diff = Math.abs(total - transactionTotalPrice()); | |
| - return diff > 0.01 || forceShowPrice ? `(${formatPrice(total)})` : ""; | |
| - }; | |
| - | |
| - const createPaymentAmountReceived = ( | |
| - paymentForm: TransactionPaymentForm, | |
| - paymentMethodId: string | undefined, | |
| - total: number, | |
| - ) => { | |
| - const amountReceived = { | |
| - amountPaid: 0, | |
| - paymentForm, | |
| - paymentMethodId, | |
| - }; | |
| - | |
| - switch (paymentForm) { | |
| - case TransactionPaymentForm.CHECK: | |
| - return { ...amountReceived, checkAmountReceived: total }; | |
| - case TransactionPaymentForm.OTHER: | |
| - return { ...amountReceived, otherAmountReceived: total }; | |
| - case TransactionPaymentForm.POINTS: | |
| - return { ...amountReceived, pointsAmountReceived: total }; | |
| - case TransactionPaymentForm["HOUSE ACCOUNT"]: | |
| - return { ...amountReceived, houseAccountAmount: total }; | |
| - default: | |
| - return amountReceived; | |
| - } | |
| - }; | |
| - | |
| - const createPaymentMethodButtons = ( | |
| - paymentForm: TransactionPaymentForm, | |
| - baseLabel: string, | |
| - baseConfig: Partial<SalesButtonGroupElement>, | |
| - ): SalesButtonGroupElement[] => { | |
| - const methodsWithPrices = calculateMethodsWithPrices(paymentForm); | |
| - | |
| - if (methodsWithPrices.length === 0) { | |
| - // Fallback: create a single button with default total when no methods available | |
| - const defaultTotal = transactionTotalPrice(); | |
| - return [ | |
| - { | |
| - ...((baseConfig as Record<string, unknown>) || {}), | |
| - label: baseLabel, | |
| - onClick: () => { | |
| - const amountReceived = createPaymentAmountReceived( | |
| - paymentForm, | |
| - undefined, // No specific payment method ID | |
| - defaultTotal, | |
| - ); | |
| - setAmountPaid(amountReceived); | |
| - onClose(); | |
| - }, | |
| - }, | |
| - ]; | |
| - } | |
| - | |
| - if ( | |
| - methodsWithPrices.length === 1 && | |
| - methodsWithPrices[0]?.total !== undefined | |
| - ) { | |
| - const paymentMethod = methodsWithPrices[0]?.method; | |
| - const methodTotal = methodsWithPrices[0]?.total; | |
| - if (!paymentMethod || !methodTotal) return []; | |
| - | |
| - return [ | |
| - { | |
| - ...((baseConfig as Record<string, unknown>) || {}), | |
| - label: `${baseLabel}${formatPriceWithCondition(paymentMethod.id, false)}`, | |
| - onClick: () => { | |
| - const amountReceived = createPaymentAmountReceived( | |
| - paymentForm, | |
| - paymentMethod.id, | |
| - methodTotal, | |
| - ); | |
| - setAmountPaid(amountReceived); | |
| - onClose(); | |
| - }, | |
| - }, | |
| - ]; | |
| - } | |
| - | |
| - return methodsWithPrices | |
| - .map(({ method, total }) => { | |
| - return { | |
| - ...((baseConfig as Record<string, unknown>) || {}), | |
| - label: `${baseLabel} ${formatPriceWithCondition(method.id, true)}`, | |
| - onClick: () => { | |
| - const amountReceived = createPaymentAmountReceived( | |
| - paymentForm, | |
| - method.id, | |
| - total, | |
| - ); | |
| - setAmountPaid(amountReceived); | |
| - onClose(); | |
| - }, | |
| - }; | |
| - }) | |
| - .filter((button) => button !== null); | |
| + const otherOption = { | |
| + label: "Other", | |
| + disabled: !transactionItems.length || inStoreChannel, | |
| + requires: "payment_option/other:use", | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| + onClick: () => { | |
| + setAmountPaid({ | |
| + amountPaid: 0, | |
| + otherAmountReceived: transactionTotalPrice(), | |
| + paymentForm: TransactionPaymentForm.OTHER, | |
| + }); | |
| + onClose(); | |
| + }, | |
| }; | |
| - | |
| - const allElements: SalesButtonGroupElement[] = []; | |
| - | |
| - // Check buttons | |
| - const checkButtons = createPaymentMethodButtons( | |
| - TransactionPaymentForm.CHECK, | |
| - "Check", | |
| + return [ | |
| { | |
| + label: "Check", | |
| requires: "payment_option/check:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| leftIcon: <FaMoneyCheck />, | |
| disabled: !transactionItems.length || notInStoreChannel, | |
| - }, | |
| - ); | |
| - allElements.push(...checkButtons); | |
| - | |
| - // Gift Card buttons (special case - opens modal) | |
| - const giftCardMethodsWithPrices = calculateMethodsWithPrices( | |
| - TransactionPaymentForm["GIFT CARD"], | |
| - ); | |
| - | |
| - if (giftCardMethodsWithPrices.length > 0) { | |
| - if ( | |
| - giftCardMethodsWithPrices.length === 1 && | |
| - giftCardMethodsWithPrices[0]?.total !== undefined | |
| - ) { | |
| - const paymentMethod = giftCardMethodsWithPrices[0]?.method; | |
| - const methodTotal = giftCardMethodsWithPrices[0]?.total; | |
| - if (!paymentMethod || !methodTotal) return []; | |
| - | |
| - allElements.push({ | |
| - label: `Gift Card${formatPriceWithCondition(paymentMethod.id, false)}`, | |
| - requires: "payment_option/gift_card:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - disabled: !transactionItems.length || notInStoreChannel, | |
| - onClick: () => { | |
| - setSelectedGiftCardPaymentMethodId(paymentMethod.id); | |
| - onClose(); | |
| - openGiftCardModal(); | |
| - }, | |
| - }); | |
| - } else { | |
| - giftCardMethodsWithPrices.forEach(({ method, total }) => { | |
| - allElements.push({ | |
| - label: `Gift Card ${formatPriceWithCondition(method.id, true)}`, | |
| - requires: "payment_option/gift_card:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - disabled: !transactionItems.length || notInStoreChannel, | |
| - onClick: () => { | |
| - setSelectedGiftCardPaymentMethodId(method.id); | |
| - onClose(); | |
| - openGiftCardModal(); | |
| - }, | |
| + onClick: () => { | |
| + setAmountPaid({ | |
| + amountPaid: 0, | |
| + checkAmountReceived: transactionTotalPrice(), | |
| + paymentForm: TransactionPaymentForm.CHECK, | |
| }); | |
| - }); | |
| - } | |
| - } else { | |
| - // Fallback: show simple Gift Card button when no methods available | |
| - allElements.push({ | |
| + onClose(); | |
| + }, | |
| + }, | |
| + { | |
| label: "Gift Card", | |
| requires: "payment_option/gift_card:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| disabled: !transactionItems.length || notInStoreChannel, | |
| onClick: () => { | |
| - setSelectedGiftCardPaymentMethodId(undefined); | |
| onClose(); | |
| openGiftCardModal(); | |
| }, | |
| - }); | |
| - } | |
| - | |
| - // Pay Later button (special case - will be deprecated) | |
| - const payLaterMethods = | |
| - paymentMethodTypeToPaymentMethod[TransactionPaymentForm.LATER] || []; | |
| - if (payLaterMethods.length > 0) { | |
| - allElements.push({ | |
| - label: `Pay Later ${formatPriceWithCondition(payLaterMethods[0]?.id)}`, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| + }, | |
| + { | |
| + label: "Pay Later", | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| requires: "payment_option/pay_later:use", | |
| disabled: | |
| !transactionItems.length || | |
| @@ -259,209 +103,49 @@ export const OtherOptionsModal = ({ | |
| checkAmountReceived: 0, | |
| creditCardAmountReceived: 0, | |
| paymentForm: TransactionPaymentForm.LATER, | |
| - paymentMethodId: payLaterMethods[0]?.id, | |
| }); | |
| onClose(); | |
| }, | |
| "data-testid": "other-options-pay-later-btn", | |
| - }); | |
| - } else { | |
| - // Fallback: show simple Pay Later button when no methods available | |
| - allElements.push({ | |
| - label: `Pay Later`, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - requires: "payment_option/pay_later:use", | |
| + }, | |
| + { | |
| + label: "Manual Card", | |
| + requires: "payment_option/manual_credit_card:use", | |
| disabled: | |
| !transactionItems.length || | |
| transactionTotalPrice() <= 0 || | |
| notInStoreChannel, | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| onClick: () => { | |
| - setAmountPaid({ | |
| - amountPaid: 0, | |
| - otherAmountReceived: 0, | |
| - checkAmountReceived: 0, | |
| - creditCardAmountReceived: 0, | |
| - paymentForm: TransactionPaymentForm.LATER, | |
| - paymentMethodId: undefined, | |
| - }); | |
| - onClose(); | |
| - }, | |
| - "data-testid": "other-options-pay-later-btn", | |
| - }); | |
| - } | |
| - | |
| - // Manual Card buttons (special case - opens modal with different prices) | |
| - const creditCardMethodsWithPrices = calculateMethodsWithPrices( | |
| - TransactionPaymentForm["CREDIT CARD"], | |
| - ); | |
| - if (creditCardMethodsWithPrices.length > 0) { | |
| - if ( | |
| - creditCardMethodsWithPrices.length === 1 && | |
| - creditCardMethodsWithPrices[0]?.total !== undefined | |
| - ) { | |
| - const paymentMethod = creditCardMethodsWithPrices[0]?.method; | |
| - const methodTotal = creditCardMethodsWithPrices[0]?.total; | |
| - if (!paymentMethod || !methodTotal) return []; | |
| - | |
| - allElements.push({ | |
| - label: `Manual Card`, | |
| - requires: "payment_option/manual_credit_card:use", | |
| - disabled: | |
| - !transactionItems.length || methodTotal <= 0 || notInStoreChannel, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - onClick: () => { | |
| - setSelectedCreditCardPrice({ | |
| - method: paymentMethod, | |
| - total: methodTotal, | |
| - }); | |
| - onClose(); | |
| - manualPunchModal.onOpen(); | |
| - }, | |
| - }); | |
| - } else { | |
| - creditCardMethodsWithPrices.forEach(({ method, total }) => { | |
| - allElements.push({ | |
| - label: `Manual Card ${formatPriceWithCondition(method.id, true)}`, | |
| - requires: "payment_option/manual_credit_card:use", | |
| - disabled: | |
| - !transactionItems.length || total <= 0 || notInStoreChannel, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - onClick: () => { | |
| - setSelectedCreditCardPrice({ method, total }); | |
| - onClose(); | |
| - manualPunchModal.onOpen(); | |
| - }, | |
| - }); | |
| - }); | |
| - } | |
| - } else { | |
| - // Fallback: show simple Manual Card button when no methods available | |
| - const defaultTotal = transactionTotalPrice(); | |
| - allElements.push({ | |
| - label: `Manual Card`, | |
| - requires: "payment_option/manual_credit_card:use", | |
| - disabled: | |
| - !transactionItems.length || defaultTotal <= 0 || notInStoreChannel, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - onClick: () => { | |
| - setSelectedCreditCardPrice({ | |
| - method: { | |
| - id: undefined, | |
| - } as unknown as EntitySalesChannelPaymentMethod, // Fallback method | |
| - total: defaultTotal, | |
| - }); | |
| onClose(); | |
| manualPunchModal.onOpen(); | |
| }, | |
| - }); | |
| - } | |
| - | |
| - // Other buttons | |
| - const otherButtons = createPaymentMethodButtons( | |
| - TransactionPaymentForm.OTHER, | |
| - "Other/External", | |
| - { | |
| - disabled: !transactionItems.length || inStoreChannel, | |
| - requires: "payment_option/other:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| }, | |
| - ); | |
| - allElements.push(...otherButtons); | |
| - | |
| - // Points buttons (special case - opens multiple payments modal) | |
| - const pointsMethods = | |
| - paymentMethodTypeToPaymentMethod[TransactionPaymentForm.POINTS] || []; | |
| - if (pointsMethods.length > 0) { | |
| - allElements.push({ | |
| - label: `Points`, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - requires: "payment_option/points:use", | |
| - disabled: !transactionItems.length || notInStoreChannel, | |
| - onClick: () => { | |
| - multiplePaymentsModal.onOpen(); | |
| - onClose(); | |
| - }, | |
| - }); | |
| - } else { | |
| - // Fallback: show simple Points button when no methods available | |
| - allElements.push({ | |
| - label: `Points`, | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| + otherOption, | |
| + { | |
| + label: "Points", | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| requires: "payment_option/points:use", | |
| disabled: !transactionItems.length || notInStoreChannel, | |
| onClick: () => { | |
| multiplePaymentsModal.onOpen(); | |
| onClose(); | |
| }, | |
| - }); | |
| - } | |
| - | |
| - // House Account buttons (special case - opens house account modal) | |
| - const houseAccountMethodsWithPrices = calculateMethodsWithPrices( | |
| - TransactionPaymentForm["HOUSE ACCOUNT"], | |
| - ); | |
| - | |
| - if (houseAccountMethodsWithPrices.length > 0) { | |
| - if ( | |
| - houseAccountMethodsWithPrices.length === 1 && | |
| - houseAccountMethodsWithPrices[0]?.total !== undefined | |
| - ) { | |
| - const paymentMethod = houseAccountMethodsWithPrices[0]?.method; | |
| - const methodTotal = houseAccountMethodsWithPrices[0]?.total; | |
| - if (!paymentMethod || !methodTotal) return []; | |
| - | |
| - allElements.push({ | |
| - label: `House Account${formatPriceWithCondition(paymentMethod.id, false)}`, | |
| - requires: "payment_option/house_account:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - disabled: | |
| - !transactionItems.length || | |
| - notInStoreChannel || | |
| - salePaymentType === "houseAccountPayment", | |
| - onClick: () => { | |
| - setSelectedHouseAccountPaymentMethodId(paymentMethod.id); | |
| - houseAccountDisclosure.onOpen(); | |
| - onClose(); | |
| - }, | |
| - }); | |
| - } else { | |
| - houseAccountMethodsWithPrices.forEach(({ method, total }) => { | |
| - allElements.push({ | |
| - label: `House Account ${formatPriceWithCondition(method.id, true)}`, | |
| - requires: "payment_option/house_account:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| - disabled: | |
| - !transactionItems.length || | |
| - notInStoreChannel || | |
| - salePaymentType === "houseAccountPayment", | |
| - onClick: () => { | |
| - setSelectedHouseAccountPaymentMethodId(method.id); | |
| - houseAccountDisclosure.onOpen(); | |
| - onClose(); | |
| - }, | |
| - }); | |
| - }); | |
| - } | |
| - } else { | |
| - // Fallback: show simple House Account button when no methods available | |
| - allElements.push({ | |
| - label: `House Account`, | |
| + }, | |
| + { | |
| + label: "House Account", | |
| requires: "payment_option/house_account:use", | |
| - className: PAYMENT_BUTTON_STYLES.BLUE, | |
| + className: "bg-blue-500 hover:bg-blue-600 w-full", | |
| disabled: | |
| !transactionItems.length || | |
| notInStoreChannel || | |
| salePaymentType === "houseAccountPayment", | |
| onClick: () => { | |
| - setSelectedHouseAccountPaymentMethodId(undefined); | |
| houseAccountDisclosure.onOpen(); | |
| onClose(); | |
| }, | |
| - }); | |
| - } | |
| - | |
| - return allElements; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| + }, | |
| + ].map((x) => ({ ...x })); | |
| }, [ | |
| salesChannel.salesChannelTypeId, | |
| entity.cohortId, | |
| @@ -474,7 +158,6 @@ export const OtherOptionsModal = ({ | |
| manualPunchModal, | |
| multiplePaymentsModal, | |
| houseAccountDisclosure, | |
| - paymentMethodTypeToPaymentMethod, | |
| ]); | |
| return ( | |
| @@ -495,14 +178,11 @@ export const OtherOptionsModal = ({ | |
| <ManualCardPunchModal | |
| isOpen={manualPunchModal.isOpen} | |
| onClose={manualPunchModal.onClose} | |
| - onSubmit={(selectedPriceOption) => { | |
| + onSubmit={() => { | |
| manualPunchModal.onClose(); | |
| creditCardModalV2.onOpen(); | |
| reviewTransactionModal.onClose(); | |
| - // TODO: Use selectedPriceOption to set the payment method for the transaction | |
| }} | |
| - selectedPriceOption={selectedCreditCardPrice} | |
| - salesChannel={salePaymentType === "sale" ? salesChannel : undefined} | |
| /> | |
| </> | |
| ); | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/buttonStyles.ts b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/buttonStyles.ts | |
| deleted file mode 100644 | |
| index cb2374ff..00000000 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/Other/buttonStyles.ts | |
| +++ /dev/null | |
| @@ -1,20 +0,0 @@ | |
| -/** | |
| - * Reusable button styling constants for payment options | |
| - */ | |
| -export const PAYMENT_BUTTON_STYLES = { | |
| - /** | |
| - * Standard blue payment button styling | |
| - */ | |
| - BLUE: "bg-blue-500 hover:bg-blue-600 w-full", | |
| - | |
| - /** | |
| - * Alternative button styling variants can be added here | |
| - */ | |
| - // GREEN: "bg-green-500 hover:bg-green-600 w-full", | |
| - // RED: "bg-red-500 hover:bg-red-600 w-full", | |
| -} as const; | |
| - | |
| -/** | |
| - * Type for button style keys | |
| - */ | |
| -export type PaymentButtonStyle = keyof typeof PAYMENT_BUTTON_STYLES; | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.test.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.test.tsx | |
| deleted file mode 100644 | |
| index 9fa3ff44..00000000 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.test.tsx | |
| +++ /dev/null | |
| @@ -1,525 +0,0 @@ | |
| -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | |
| -import { fireEvent, render, screen } from "@testing-library/react"; | |
| -import { TransactionPaymentForm } from "src/generated"; | |
| -import { | |
| - createMockSalesContext, | |
| - createMockSalesPaymentContext, | |
| -} from "src/test-utils"; | |
| -import { MockEntityProvider } from "src/test/mocks/entityProvider"; | |
| -import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| -import { PaymentOptions } from "./PaymentOptions"; | |
| - | |
| -// Create mocks using the consolidated functions | |
| -const mockSalesContext = createMockSalesContext(); | |
| -const mockSalesPaymentContext = createMockSalesPaymentContext(); | |
| - | |
| -// Mock the SalesContext | |
| -vi.mock("src/context/Sales/SalesContext", () => ({ | |
| - useSalesContext: () => mockSalesContext, | |
| -})); | |
| - | |
| -// Mock the SalesPaymentContext | |
| -vi.mock("src/context/Sales/SalesPaymentContext", () => ({ | |
| - useSalesPaymentContext: () => mockSalesPaymentContext, | |
| -})); | |
| - | |
| -// Mock the payment method disable functions | |
| -vi.mock("components/payment/disablePaymentMethods", () => ({ | |
| - isNotInStoreChannel: vi.fn(() => false), | |
| -})); | |
| - | |
| -// Mock the MultiplePayments component | |
| -vi.mock("../../../MultiplePayments", () => ({ | |
| - default: ({ | |
| - disabled, | |
| - transactionTotalPrice, | |
| - onSubmit, | |
| - multiplePaymentsDisclosure, | |
| - }: any) => ( | |
| - <button | |
| - data-testid="multiple-payments-component" | |
| - disabled={disabled} | |
| - onClick={() => { | |
| - // Simulate the onSubmit call with mock payment data | |
| - onSubmit({ | |
| - cash: 10.0, | |
| - creditCard: 15.0, | |
| - creditCard2: 5.0, | |
| - creditCard3: 0, | |
| - check: 7.5, | |
| - other: 2.5, | |
| - giftCard: 0, | |
| - pointsDollars: 0, | |
| - houseAccountAmount: 0, | |
| - houseAccountId: "", | |
| - giftCardId: "", | |
| - }); | |
| - }} | |
| - > | |
| - Multiple Payments (${transactionTotalPrice || 0}) | |
| - </button> | |
| - ), | |
| -})); | |
| - | |
| -// Mock the modals | |
| -vi.mock("./GiftCards/GiftCardSaleModal", () => ({ | |
| - GiftCardSaleModal: ({ isOpen, onClose, onClick }: any) => ( | |
| - <div data-testid="gift-card-sale-modal"> | |
| - {isOpen && ( | |
| - <div> | |
| - <button onClick={onClose}>Close Gift Card Modal</button> | |
| - <button | |
| - onClick={() => onClick({ code: "GIFT123" })} | |
| - data-testid="gift-card-submit" | |
| - > | |
| - Submit Gift Card | |
| - </button> | |
| - </div> | |
| - )} | |
| - </div> | |
| - ), | |
| -})); | |
| - | |
| -vi.mock("./Other/HouseAccountPaymentModal", () => ({ | |
| - HouseAccountPaymentModal: ({ isOpen, onClose }: any) => ( | |
| - <div data-testid="house-account-payment-modal"> | |
| - {isOpen && ( | |
| - <div> | |
| - <button onClick={onClose}>Close House Account Modal</button> | |
| - </div> | |
| - )} | |
| - </div> | |
| - ), | |
| -})); | |
| - | |
| -vi.mock("./Other/OtherOptionsModal", () => ({ | |
| - OtherOptionsModal: ({ | |
| - disclosure, | |
| - giftCardDisclosure, | |
| - houseAccountDisclosure, | |
| - }: any) => ( | |
| - <div data-testid="other-options-modal"> | |
| - {disclosure.isOpen && ( | |
| - <div> | |
| - <button onClick={disclosure.onClose}>Close Other Options</button> | |
| - <button onClick={giftCardDisclosure.onOpen}>Open Gift Card</button> | |
| - <button onClick={houseAccountDisclosure.onOpen}> | |
| - Open House Account | |
| - </button> | |
| - </div> | |
| - )} | |
| - </div> | |
| - ), | |
| -})); | |
| - | |
| -// Test wrapper component | |
| -const TestWrapper = ({ children }: { children: React.ReactNode }) => { | |
| - const queryClient = new QueryClient({ | |
| - defaultOptions: { | |
| - queries: { retry: false }, | |
| - mutations: { retry: false }, | |
| - }, | |
| - }); | |
| - | |
| - return ( | |
| - <QueryClientProvider client={queryClient}> | |
| - <MockEntityProvider | |
| - entityOverrides={{ creditCardMerchantId: "merchant123" }} | |
| - > | |
| - {children} | |
| - </MockEntityProvider> | |
| - </QueryClientProvider> | |
| - ); | |
| -}; | |
| - | |
| -describe("PaymentOptions", () => { | |
| - beforeEach(() => { | |
| - vi.clearAllMocks(); | |
| - | |
| - // Reset calculateMethodsWithPrices mock to default behavior | |
| - mockSalesContext.calculateMethodsWithPrices.mockReturnValue([ | |
| - { method: { id: "test-method", name: "Test Method" }, total: 40.0 }, | |
| - ]); | |
| - | |
| - // Reset context to default state | |
| - Object.assign(mockSalesPaymentContext, { | |
| - isPersisting: false, | |
| - isCalculatingCartPrice: false, | |
| - transactionItems: [ | |
| - { id: 1, name: "Test Item", price: 10.0, quantity: 1 }, | |
| - { id: 2, name: "Test Item 2", price: 15.0, quantity: 2 }, | |
| - ], | |
| - }); | |
| - }); | |
| - | |
| - it("renders payment option buttons", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Should render Credit Card button with pricing | |
| - expect(screen.getByText(/Credit \(\$40\.00\)/)).toBeInTheDocument(); | |
| - | |
| - // Should render Multiple Payments component | |
| - expect( | |
| - screen.getByTestId("multiple-payments-component"), | |
| - ).toBeInTheDocument(); | |
| - | |
| - // Should render Other Options button | |
| - expect( | |
| - screen.getByTestId("other-payment-options-button"), | |
| - ).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("calculates and displays correct pricing for credit card payment", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Verify calculateMethodsWithPrices was called with CREDIT CARD payment form | |
| - expect( | |
| - mockSalesPaymentContext.calculateMethodsWithPrices, | |
| - ).toHaveBeenCalledWith(TransactionPaymentForm["CREDIT CARD"]); | |
| - | |
| - // Should display the formatted price in the button label | |
| - expect(screen.getByText(/Credit \(\$40\.00\)/)).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("calculates and displays correct pricing for cash payment", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // The cash total should be calculated (though not directly displayed in button) | |
| - // PaymentOptions component doesn't directly call calculateMethodsWithPrices for CASH | |
| - // It only calls it for credit cards via CreditCardOptions | |
| - }); | |
| - | |
| - it("handles credit card button click correctly", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const creditCardButton = screen.getByText(/Credit \(\$40\.00\)/); | |
| - | |
| - if (!creditCardButton.hasAttribute("disabled")) { | |
| - fireEvent.click(creditCardButton); | |
| - | |
| - expect(mockSalesPaymentContext.creditCardPaid).toHaveBeenCalled(); | |
| - expect( | |
| - mockSalesPaymentContext.creditCardModalV2.onOpen, | |
| - ).toHaveBeenCalled(); | |
| - expect( | |
| - mockSalesPaymentContext.reviewTransactionModal.onClose, | |
| - ).toHaveBeenCalled(); | |
| - } | |
| - }); | |
| - | |
| - it("opens other options modal when Other Options is clicked", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const otherOptionsButton = screen.getByTestId( | |
| - "other-payment-options-button", | |
| - ); | |
| - | |
| - if (!otherOptionsButton.hasAttribute("disabled")) { | |
| - fireEvent.click(otherOptionsButton); | |
| - expect( | |
| - mockSalesPaymentContext.otherPaymentsModal.onOpen, | |
| - ).toHaveBeenCalled(); | |
| - } | |
| - }); | |
| - | |
| - it("handles multiple payments submission correctly", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const multiplePaymentsButton = screen.getByTestId( | |
| - "multiple-payments-component", | |
| - ); | |
| - | |
| - if (!multiplePaymentsButton.hasAttribute("disabled")) { | |
| - fireEvent.click(multiplePaymentsButton); | |
| - | |
| - expect(mockSalesPaymentContext.setAmountPaid).toHaveBeenCalledWith({ | |
| - amountPaid: 10.0, | |
| - creditCardAmountReceived: 15.0, | |
| - creditCardAmountReceived2: 5.0, | |
| - creditCardAmountReceived3: 0, | |
| - checkAmountReceived: 7.5, | |
| - otherAmountReceived: 2.5, | |
| - giftCardAmountReceived: 0, | |
| - pointsAmountReceived: 0, | |
| - houseAccountAmount: 0, | |
| - houseAccountId: "", | |
| - paymentForm: TransactionPaymentForm.MULTIPLE, | |
| - giftCardId: "", | |
| - }); | |
| - } | |
| - }); | |
| - | |
| - it("opens credit card modal when multiple payments includes credit card", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const multiplePaymentsButton = screen.getByTestId( | |
| - "multiple-payments-component", | |
| - ); | |
| - | |
| - if (!multiplePaymentsButton.hasAttribute("disabled")) { | |
| - fireEvent.click(multiplePaymentsButton); | |
| - | |
| - // Should open credit card modal since mock data includes creditCard: 15.0 | |
| - expect( | |
| - mockSalesPaymentContext.multiplePaymentsModal.onClose, | |
| - ).toHaveBeenCalled(); | |
| - expect( | |
| - mockSalesPaymentContext.creditCardModalV2.onOpen, | |
| - ).toHaveBeenCalled(); | |
| - expect( | |
| - mockSalesPaymentContext.reviewTransactionModal.onClose, | |
| - ).toHaveBeenCalled(); | |
| - } | |
| - }); | |
| - | |
| - it("passes correct transaction total to multiple payments component", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // The MultiplePayments component should receive the transaction total | |
| - expect(screen.getByText("Multiple Payments ($40)")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("disables credit card button when no merchant ID", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // With merchant ID, button should not be disabled due to merchant ID | |
| - const creditCardButton = screen.getByText(/Credit \(\$40\.00\)/); | |
| - // We can't easily test the disabled state without mocking the entity, | |
| - // but we can verify the button exists | |
| - expect(creditCardButton).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("disables buttons when no transaction items", () => { | |
| - // Update mock to have no transaction items | |
| - Object.assign(mockSalesPaymentContext, { | |
| - transactionItems: [], | |
| - }); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const creditCardButton = screen.getByText(/Credit \(\$40\.00\)/); | |
| - const multiplePaymentsButton = screen.getByTestId( | |
| - "multiple-payments-component", | |
| - ); | |
| - const otherOptionsButton = screen.getByTestId( | |
| - "other-payment-options-button", | |
| - ); | |
| - | |
| - expect(creditCardButton).toBeDisabled(); | |
| - expect(multiplePaymentsButton).toBeDisabled(); | |
| - expect(otherOptionsButton).toBeDisabled(); | |
| - }); | |
| - | |
| - it("disables buttons when persisting", () => { | |
| - // Update mock to be in persisting state | |
| - Object.assign(mockSalesPaymentContext, { | |
| - isPersisting: true, | |
| - }); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const creditCardButton = screen.getByText(/Credit \(\$40\.00\)/); | |
| - const multiplePaymentsButton = screen.getByTestId( | |
| - "multiple-payments-component", | |
| - ); | |
| - const otherOptionsButton = screen.getByTestId( | |
| - "other-payment-options-button", | |
| - ); | |
| - | |
| - expect(creditCardButton).toBeDisabled(); | |
| - expect(multiplePaymentsButton).toBeDisabled(); | |
| - expect(otherOptionsButton).toBeDisabled(); | |
| - }); | |
| - | |
| - it("disables buttons when calculating cart price", () => { | |
| - // Update mock to be calculating cart price | |
| - Object.assign(mockSalesPaymentContext, { | |
| - isCalculatingCartPrice: true, | |
| - }); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const creditCardButton = screen.getByText(/Credit \(\$40\.00\)/); | |
| - const multiplePaymentsButton = screen.getByTestId( | |
| - "multiple-payments-component", | |
| - ); | |
| - const otherOptionsButton = screen.getByTestId( | |
| - "other-payment-options-button", | |
| - ); | |
| - | |
| - expect(creditCardButton).toBeDisabled(); | |
| - expect(multiplePaymentsButton).toBeDisabled(); | |
| - expect(otherOptionsButton).toBeDisabled(); | |
| - }); | |
| - | |
| - it("disables credit card button when payment total is zero or negative", () => { | |
| - // Mock transactionTotalPrice to return 0 for credit card | |
| - (mockSalesPaymentContext.transactionTotalPrice as any).mockImplementation( | |
| - (items: any, paymentForm: any) => { | |
| - if (paymentForm === TransactionPaymentForm["CREDIT CARD"]) return 0; | |
| - if (paymentForm === TransactionPaymentForm.CASH) return 40.0; | |
| - return 40.0; | |
| - }, | |
| - ); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const creditCardButton = screen.getByText(/Credit \(\$40\.00\)/); | |
| - expect(creditCardButton).toBeDisabled(); | |
| - }); | |
| - | |
| - it("renders gift card modal component when not open", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // The gift card modal is conditionally rendered based on isOpen state | |
| - // When closed, it should not be in the DOM | |
| - expect( | |
| - screen.queryByTestId("gift-card-sale-modal"), | |
| - ).not.toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("uses correct payment form constants", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Verify that the component calls transactionTotalPrice with correct payment forms | |
| - expect( | |
| - mockSalesPaymentContext.calculateMethodsWithPrices, | |
| - ).toHaveBeenCalledWith(TransactionPaymentForm["CREDIT CARD"]); | |
| - }); | |
| - | |
| - it("formats payment method totals correctly", () => { | |
| - // Set up specific return values | |
| - (mockSalesPaymentContext.transactionTotalPrice as any).mockImplementation( | |
| - (items: any, paymentForm: any) => { | |
| - if (paymentForm === TransactionPaymentForm["CREDIT CARD"]) | |
| - return 123.45; | |
| - if (paymentForm === TransactionPaymentForm.CASH) return 67.89; | |
| - return 40.0; | |
| - }, | |
| - ); | |
| - | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Should display formatted credit card total in button | |
| - expect(screen.getByText(/Credit \(\$40\.00\)/)).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("renders multiple payments component with correct structure", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - const multiplePaymentsComponent = screen.getByTestId( | |
| - "multiple-payments-component", | |
| - ); | |
| - | |
| - // Should render the multiple payments component | |
| - expect(multiplePaymentsComponent).toBeInTheDocument(); | |
| - | |
| - // Should not be disabled with valid transaction items | |
| - expect(multiplePaymentsComponent).not.toBeDisabled(); | |
| - | |
| - // Should contain "Multiple Payments" text | |
| - expect(multiplePaymentsComponent).toHaveTextContent(/Multiple Payments/); | |
| - }); | |
| - | |
| - it("handles custom button sizes", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions buttonSize="lg" /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Component should render without errors with custom button size | |
| - expect(screen.getByText(/Credit \(\$40\.00\)/)).toBeInTheDocument(); | |
| - expect( | |
| - screen.getByTestId("multiple-payments-component"), | |
| - ).toBeInTheDocument(); | |
| - expect( | |
| - screen.getByTestId("other-payment-options-button"), | |
| - ).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("handles custom button justification", () => { | |
| - render( | |
| - <TestWrapper> | |
| - <PaymentOptions justifyButtons="center" /> | |
| - </TestWrapper>, | |
| - ); | |
| - | |
| - // Component should render without errors with custom justification | |
| - expect(screen.getByText(/Credit \(\$40\.00\)/)).toBeInTheDocument(); | |
| - expect( | |
| - screen.getByTestId("multiple-payments-component"), | |
| - ).toBeInTheDocument(); | |
| - expect( | |
| - screen.getByTestId("other-payment-options-button"), | |
| - ).toBeInTheDocument(); | |
| - }); | |
| -}); | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.tsx | |
| index 30dbef5b..636806c1 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/PaymentOptions/PaymentOptions.tsx | |
| @@ -4,11 +4,15 @@ import { ButtonSize } from "components/ui/button"; | |
| import { shadcnResponsiveButtonSizes } from "config/styles/button"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| import { TransactionPaymentForm } from "generated/types"; | |
| -import { useMemo, useState } from "react"; | |
| +import { useMemo } from "react"; | |
| +import { FaCreditCard } from "react-icons/fa"; | |
| import { useEntitySelected } from "src/context/EntityProvider"; | |
| import MultiplePayments from "../../../MultiplePayments"; | |
| -import { SalesButtonGroup, SalesButtonGroupElement } from "../SalesButtonGroup"; | |
| -import { CreditCardOptions } from "./CreditCardOptions"; | |
| +import { | |
| + SalesButton, | |
| + SalesButtonGroup, | |
| + SalesButtonGroupElement, | |
| +} from "../SalesButtonGroup"; | |
| import { GiftCardSaleModal } from "./GiftCards/GiftCardSaleModal"; | |
| import { HouseAccountPaymentModal } from "./Other/HouseAccountPaymentModal"; | |
| import { OtherOptionsModal } from "./Other/OtherOptionsModal"; | |
| @@ -22,19 +26,13 @@ export interface PaymentOptionsProps { | |
| export const PaymentOptions: React.FC<PaymentOptionsProps> = ({ | |
| buttonSize, | |
| justifyButtons, | |
| - onSubmit, | |
| }) => { | |
| - const [ | |
| - selectedHouseAccountPaymentMethodId, | |
| - setSelectedHouseAccountPaymentMethodId, | |
| - ] = useState<string | undefined>(); | |
| - const [selectedGiftCardPaymentMethodId, setSelectedGiftCardPaymentMethodId] = | |
| - useState<string | undefined>(); | |
| const [entity] = useEntitySelected(); | |
| const { | |
| transactionItems, | |
| transactionTotalPrice, | |
| setAmountPaid, | |
| + creditCardPaid, | |
| creditCardModalV2, | |
| otherPaymentsModal, | |
| multiplePaymentsModal, | |
| @@ -51,12 +49,29 @@ export const PaymentOptions: React.FC<PaymentOptionsProps> = ({ | |
| cohortId: entity.cohortId, | |
| }); | |
| - // Create credit card button configurations outside of useMemo to avoid hooks rule violation | |
| - const creditCardButtons = CreditCardOptions({ buttonSize, onSubmit }); | |
| - | |
| const elements: SalesButtonGroupElement[] = useMemo(() => { | |
| return [ | |
| - ...creditCardButtons, | |
| + { | |
| + label: "Credit (F8)", | |
| + leftIcon: <FaCreditCard />, | |
| + requires: "payment_option/credit_card:use", | |
| + size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| + disabled: | |
| + !transactionItems.length || | |
| + !entity.creditCardMerchantId || | |
| + isPersisting || | |
| + transactionTotalPrice() <= 0 || | |
| + isCalculatingCartPrice || | |
| + notInStoreChannel, | |
| + onClick: (e) => { | |
| + e.preventDefault(); | |
| + e.stopPropagation(); | |
| + e.currentTarget.blur(); | |
| + creditCardPaid(); | |
| + creditCardModalV2.onOpen(); | |
| + reviewTransactionModal.onClose(); | |
| + }, | |
| + } as SalesButton, | |
| <MultiplePayments | |
| disabled={ | |
| !transactionItems.length || | |
| @@ -106,15 +121,16 @@ export const PaymentOptions: React.FC<PaymentOptionsProps> = ({ | |
| size: buttonSize ?? shadcnResponsiveButtonSizes, | |
| }, | |
| ].filter((x) => !!x); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| - creditCardButtons, | |
| + buttonSize, | |
| transactionItems.length, | |
| + entity?.creditCardMerchantId, | |
| isPersisting, | |
| transactionTotalPrice, | |
| isCalculatingCartPrice, | |
| notInStoreChannel, | |
| multiplePaymentsModal, | |
| + creditCardPaid, | |
| creditCardModalV2, | |
| reviewTransactionModal, | |
| setAmountPaid, | |
| @@ -132,15 +148,11 @@ export const PaymentOptions: React.FC<PaymentOptionsProps> = ({ | |
| <GiftCardSaleModal | |
| isOpen={giftCardSalesModal.isOpen} | |
| onClose={giftCardSalesModal.onClose} | |
| - paymentMethodId={selectedGiftCardPaymentMethodId} | |
| onClick={(giftCardSale) => { | |
| setAmountPaid({ | |
| amountPaid: 0, | |
| - giftCardAmountReceived: transactionTotalPrice({ | |
| - paymentMethodId: selectedGiftCardPaymentMethodId, | |
| - }), | |
| + giftCardAmountReceived: transactionTotalPrice(), | |
| paymentForm: TransactionPaymentForm["GIFT CARD"], | |
| - paymentMethodId: selectedGiftCardPaymentMethodId, | |
| giftCardId: giftCardSale.code, | |
| }); | |
| // reviewTransactionModal.onOpen(); | |
| @@ -151,16 +163,11 @@ export const PaymentOptions: React.FC<PaymentOptionsProps> = ({ | |
| giftCardDisclosure={giftCardSalesModal} | |
| houseAccountDisclosure={houseAccountPaymentModal} | |
| disclosure={otherPaymentsModal} | |
| - setSelectedHouseAccountPaymentMethodId={ | |
| - setSelectedHouseAccountPaymentMethodId | |
| - } | |
| - setSelectedGiftCardPaymentMethodId={setSelectedGiftCardPaymentMethodId} | |
| // openChangeDueModal={reviewTransactionModal.onOpen} | |
| /> | |
| <HouseAccountPaymentModal | |
| isOpen={houseAccountPaymentModal.isOpen} | |
| onClose={houseAccountPaymentModal.onClose} | |
| - paymentMethodId={selectedHouseAccountPaymentMethodId} | |
| /> | |
| </> | |
| ); | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/QuickPicks/HotKeyButton.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/QuickPicks/HotKeyButton.tsx | |
| index 32bb7403..a8f6a569 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/QuickPicks/HotKeyButton.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/QuickPicks/HotKeyButton.tsx | |
| @@ -1,16 +1,18 @@ | |
| -import { usePGlite } from "@electric-sql/pglite-react"; | |
| import { useQueryClient } from "@tanstack/react-query"; | |
| -import { | |
| - RetrieveItemsByUpc, | |
| - RetrieveItemsByUpcQuery, | |
| -} from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { Button } from "components/ui/button"; | |
| import { toast } from "components/ui/use-toast"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| import { useSalesContext } from "context/Sales/SalesContext"; | |
| +import { useGetAllDepartmentsForEntity } from "hooks/useGetAllDepartmentsForEntity"; | |
| import { useCallback } from "react"; | |
| -import { getFilteredItemsQueryOptions } from "src/spring-generated"; | |
| +import { | |
| + CohortItemDb, | |
| + getFilteredItemsQueryOptions, | |
| + listCohortItemsQueryOptions, | |
| +} from "src/spring-generated"; | |
| +import { isDefined } from "utils/arrayUtils"; | |
| +import { toEntityItemDetail } from "utils/itemUtils"; | |
| export interface HotKeyButtonProps { | |
| label: string; | |
| @@ -19,10 +21,9 @@ export interface HotKeyButtonProps { | |
| export const HotKeyButton = ({ label, itemFilterId }: HotKeyButtonProps) => { | |
| const [entity] = useEntitySelected(); | |
| + const { departmentKeyMap } = useGetAllDepartmentsForEntity(); | |
| const queryClient = useQueryClient(); | |
| const { handleRetrievedItems, quantity } = useSalesContext(); | |
| - const db = usePGlite(); | |
| - | |
| const retrieveItemsUsingFilter = useCallback( | |
| async (filterIds: string[]) => { | |
| try { | |
| @@ -32,18 +33,47 @@ export const HotKeyButton = ({ label, itemFilterId }: HotKeyButtonProps) => { | |
| }), | |
| ); | |
| const entityItems = items.content ?? []; | |
| - const options = RetrieveItemsByUpcQuery( | |
| - entity.id, | |
| - null, | |
| - entityItems.map((item) => item.id), | |
| - ); | |
| - console.log("Retrieving items using filter", options); | |
| - const eRes = await db.query<RetrieveItemsByUpc>( | |
| - options.query, | |
| - options.params, | |
| + | |
| + const cohortItemIds = entityItems | |
| + .map((item) => item.cohortItemId) | |
| + .filter(isDefined); | |
| + | |
| + const cohortItems = | |
| + cohortItemIds.length > 0 | |
| + ? await queryClient.fetchQuery( | |
| + listCohortItemsQueryOptions({ | |
| + ids: cohortItemIds, | |
| + cohortId: entity.cohortId, | |
| + }), | |
| + ) | |
| + : undefined; | |
| + | |
| + const cohortItemMap = new Map<number, CohortItemDb>( | |
| + cohortItems?.content?.map((item) => [item.id, item]) ?? [], | |
| ); | |
| - await handleRetrievedItems(eRes.rows, quantity); | |
| + const entityItemDetails = entityItems | |
| + .map((item) => { | |
| + if (!item.cohortItemId) { | |
| + throw new Error("Cohort item id is undefined"); | |
| + } | |
| + const cohortItem = cohortItemMap.get(item.cohortItemId); | |
| + if (!cohortItem) { | |
| + throw new Error("Cohort item is undefined"); | |
| + } | |
| + const departmentId = cohortItem.departmentId; | |
| + if (!departmentId) { | |
| + throw new Error("Cohort item department id is undefined"); | |
| + } | |
| + const department = departmentKeyMap?.get(departmentId); | |
| + if (!department) { | |
| + throw new Error("Department is undefined"); | |
| + } | |
| + return toEntityItemDetail(item, cohortItem, department); | |
| + }) | |
| + .filter(isDefined); | |
| + | |
| + await handleRetrievedItems(entityItemDetails, quantity); | |
| } catch (error) { | |
| console.error(error); | |
| captureException(error); | |
| @@ -54,7 +84,13 @@ export const HotKeyButton = ({ label, itemFilterId }: HotKeyButtonProps) => { | |
| }); | |
| } | |
| }, | |
| - [queryClient, entity.id, db, handleRetrievedItems, quantity], | |
| + [ | |
| + queryClient, | |
| + entity.cohortId, | |
| + handleRetrievedItems, | |
| + quantity, | |
| + departmentKeyMap, | |
| + ], | |
| ); | |
| return ( | |
| <Button | |
| diff --git a/src/components/SalesScreenComponents/SalesButtonGroups/SalesButtonGroup.tsx b/src/components/SalesScreenComponents/SalesButtonGroups/SalesButtonGroup.tsx | |
| index 3879e887..9e8795fb 100644 | |
| --- a/src/components/SalesScreenComponents/SalesButtonGroups/SalesButtonGroup.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesButtonGroups/SalesButtonGroup.tsx | |
| @@ -1,18 +1,12 @@ | |
| -import { | |
| - Flex, | |
| - WrapItem, | |
| - type WrapItemProps, | |
| - type WrapProps, | |
| -} from "@chakra-ui/react"; | |
| +import { Flex, WrapItem, WrapItemProps, WrapProps } from "@chakra-ui/react"; | |
| import { Card } from "components/ui/card"; | |
| import { shadcnResponsiveButtonSizes } from "config/styles/button"; | |
| -import type React from "react"; | |
| -import { memo } from "react"; | |
| +import React, { memo } from "react"; | |
| import { usePermissions } from "src/context/PermissionsContext"; | |
| import { cn } from "src/lib/utils"; | |
| import { | |
| PermissionedButton, | |
| - type PermissionedButtonProps, | |
| + PermissionedButtonProps, | |
| } from "../../Auth/PermissionedButton"; | |
| export interface SalesButton extends PermissionedButtonProps { | |
| diff --git a/src/components/SalesScreenComponents/SalesScreenItemsTable.tsx b/src/components/SalesScreenComponents/SalesScreenItemsTable.tsx | |
| index 5bdcc65b..c17a9d76 100644 | |
| --- a/src/components/SalesScreenComponents/SalesScreenItemsTable.tsx | |
| +++ b/src/components/SalesScreenComponents/SalesScreenItemsTable.tsx | |
| @@ -6,13 +6,8 @@ import { | |
| } from "@/generated"; | |
| import { WarningIcon } from "@chakra-ui/icons"; | |
| import { HStack, Icon, IconButton, Text, Tooltip } from "@chakra-ui/react"; | |
| -import { usePGlite } from "@electric-sql/pglite-react"; | |
| import { createColumnHelper } from "@tanstack/react-table"; | |
| import { CanceledError } from "axios"; | |
| -import { | |
| - RetrieveItemsByUpc, | |
| - RetrieveItemsByUpcQuery, | |
| -} from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { Checkbox } from "components/ui/checkbox"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| @@ -34,7 +29,9 @@ import { | |
| import { FaSnowflake } from "react-icons/fa"; | |
| import { MdDiscount } from "react-icons/md"; | |
| import { useEntityConfig } from "src/hooks/useEntityConfig"; | |
| +import { EntityItem } from "src/model/data-contracts"; | |
| import { USDollar } from "utils/dollarFormat"; | |
| +import usePoleDisplay from "../PoleDisplay"; | |
| import { CurrencyRow } from "../Table/CurrencyRow"; | |
| import { TransformityTable } from "../Table/TransformityTable"; | |
| import { NumberInputWithSideSteppers } from "../common/NumberInputWithSideSteppers"; | |
| @@ -48,6 +45,7 @@ export interface SalesScreenItemsTableProps { | |
| } | |
| type ItemWithQtyProps = LineItem & { | |
| + poleDisplay: ReturnType<typeof usePoleDisplay>; | |
| addSingleItemToCart: SalesContextType["addSingleItemToCart"]; | |
| setItemDetails: Dispatch<SetStateAction<Map<number, LineItem>>>; | |
| calculateCartPrice: SalesContextType["calculateCartPrice"]; | |
| @@ -65,8 +63,7 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| transactionTotalPrice, | |
| }) => { | |
| const { hasPermission } = usePermissions(); | |
| - const [selectedItem, setSelectedItem] = useState<RetrieveItemsByUpc>(); | |
| - const db = usePGlite(); | |
| + const [selectedItem, setSelectedItem] = useState<EntityItem>(); | |
| const [selectedItemDetails, setSelectedItemDetails] = | |
| useState<EntityItemDetail>(); | |
| const [discountingItem, setDiscountingItem] = useState<LineItem>(); | |
| @@ -79,12 +76,12 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| calculateCartPrice, | |
| discount, | |
| addSingleItemToCart, | |
| - hasMultiplePriceLevelsOnSalesChannel, | |
| } = useSalesContext(); | |
| + const poleDisplay = usePoleDisplay(); | |
| const [entity] = useEntitySelected(); | |
| const { register } = useRegisterProvider(); | |
| const { data } = useGetItemById( | |
| - selectedItem ? selectedItem.ei_id : -1, | |
| + selectedItem ? selectedItem.id : -1, | |
| {}, | |
| { | |
| query: { | |
| @@ -125,13 +122,17 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| requestTaxExempt: taxExempt, | |
| requestedDiscount: discount, | |
| }); | |
| - | |
| + if (lineItem) { | |
| + void poleDisplay( | |
| + ``, | |
| + `Grand Total $${transactionTotalPrice(newItems).toFixed(2)}`, | |
| + ); | |
| + } | |
| setItemDetails(newItems); | |
| } catch (err) { | |
| // | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| entity?.id, | |
| register.isRegisterOpen, | |
| @@ -139,6 +140,7 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| items, | |
| calculateCartPrice, | |
| setItemDetails, | |
| + poleDisplay, | |
| transactionTotalPrice, | |
| ], | |
| ); | |
| @@ -278,7 +280,7 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| <Icon as={WarningIcon} color="orange" /> | |
| </Tooltip> | |
| )} | |
| - {row.original.item?.ei_fridge_location && ( | |
| + {row.original.item?.fridgeLocation && ( | |
| <Icon as={FaSnowflake}></Icon> | |
| )} | |
| </HStack> | |
| @@ -322,11 +324,7 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| }} | |
| /> | |
| ); | |
| - if ( | |
| - hasPermission("pos/*:edit-price") && | |
| - salePriceEditEnabled && | |
| - !hasMultiplePriceLevelsOnSalesChannel | |
| - ) { | |
| + if (hasPermission("pos/*:edit-price") && salePriceEditEnabled) { | |
| return editablePrice; | |
| } | |
| @@ -373,6 +371,12 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| lineItem, | |
| qtyIncrement ?? val - lineItem.quantity, | |
| ); | |
| + void lineItem.poleDisplay( | |
| + `${lineItem.quantity} ${lineItem.name | |
| + .trim() | |
| + .substring(0, 9)} ${lineItem.price?.toFixed(2)}`, | |
| + `${lineItem.transactionTotalPrice().toFixed(2)}`, | |
| + ); | |
| } catch (err) { | |
| if (err instanceof CanceledError) { | |
| return; | |
| @@ -495,7 +499,6 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| ), | |
| }), | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [departmentMap, hasPermission, salePriceEditEnabled], | |
| ); | |
| return ( | |
| @@ -509,6 +512,7 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| columns={columns} | |
| data={[...items.values()].map((i) => ({ | |
| ...i, | |
| + poleDisplay, | |
| transactionTotalPrice, | |
| setItemDetails, | |
| addSingleItemToCart, | |
| @@ -556,12 +560,7 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| setSelectedItemDetails(undefined); | |
| }} | |
| selectedCohortItemId={selectedItemDetails.cohortItemId} | |
| - onUpdateSuccess={async (item) => { | |
| - const options = RetrieveItemsByUpcQuery(entity.id, null, [item.id]); | |
| - const eRes = await db.query<RetrieveItemsByUpc>( | |
| - options.query, | |
| - options.params, | |
| - ); | |
| + onUpdateSuccess={(item) => { | |
| setItemDetails((prev) => { | |
| const m = new Map(prev); | |
| const lineItem = [...m.values()].find( | |
| @@ -576,7 +575,8 @@ export const SalesScreenItemsTable: React.FC<SalesScreenItemsTableProps> = ({ | |
| return item.price; | |
| } | |
| }; | |
| - lineItem.item = eRes.rows?.[0]; | |
| + lineItem.item = item; | |
| + lineItem.price = updatedPrice(); | |
| m.set(lineItem.id, lineItem); | |
| } | |
| calculateCartPrice({ | |
| diff --git a/src/components/SalesScreenComponents/Settings/SalePageSettingsButton.tsx b/src/components/SalesScreenComponents/Settings/SalePageSettingsButton.tsx | |
| index 5d93ceac..5007dd28 100644 | |
| --- a/src/components/SalesScreenComponents/Settings/SalePageSettingsButton.tsx | |
| +++ b/src/components/SalesScreenComponents/Settings/SalePageSettingsButton.tsx | |
| @@ -9,12 +9,7 @@ import SalePageSettingsDialog from "./SalePageSettingsDialog"; | |
| const SalePageSettingsButton = () => { | |
| const disclosure = useDisclosure(); | |
| - const { | |
| - selectedSalesChannel, | |
| - selectSalesChannel, | |
| - selectOverriddenCohortPriceLevel, | |
| - overriddenCohortPriceLevel, | |
| - } = useSalePageConfig(); | |
| + const { selectedSalesChannel, selectSalesChannel } = useSalePageConfig(); | |
| const { | |
| draftTransaction, | |
| calculateCartPrice, | |
| @@ -27,7 +22,6 @@ const SalePageSettingsButton = () => { | |
| const onSalesChannelSelected = useCallback( | |
| async (salesChannel: EntitySalesChannel) => { | |
| void selectSalesChannel(salesChannel); | |
| - void selectOverriddenCohortPriceLevel(undefined); | |
| await draftTransaction({ | |
| salesChannelId: salesChannel.id, | |
| }); | |
| @@ -38,7 +32,6 @@ const SalePageSettingsButton = () => { | |
| requestedDiscount: discount, | |
| }); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| selectSalesChannel, | |
| draftTransaction, | |
| @@ -50,28 +43,6 @@ const SalePageSettingsButton = () => { | |
| ], | |
| ); | |
| - const onOverriddenCohortPriceLevelSelected = useCallback( | |
| - async (priceLevelId: number | undefined) => { | |
| - void selectOverriddenCohortPriceLevel(priceLevelId); | |
| - await calculateCartPrice({ | |
| - requestedItems: items, | |
| - requestedCustomer: customer, | |
| - requestTaxExempt: taxExempt, | |
| - requestedDiscount: discount, | |
| - overriddenPriceLevel: priceLevelId, | |
| - hasOverriddenPriceLevel: true, | |
| - }); | |
| - }, | |
| - [ | |
| - selectOverriddenCohortPriceLevel, | |
| - calculateCartPrice, | |
| - items, | |
| - customer, | |
| - taxExempt, | |
| - discount, | |
| - ], | |
| - ); | |
| - | |
| return ( | |
| <> | |
| <Button variant="ghost" size="icon" onClick={disclosure.onOpen}> | |
| @@ -82,10 +53,6 @@ const SalePageSettingsButton = () => { | |
| onClose={disclosure.onClose} | |
| selectedSalesChannel={selectedSalesChannel} | |
| onSalesChannelSelected={onSalesChannelSelected} | |
| - onOverriddenCohortPriceLevelSelected={ | |
| - onOverriddenCohortPriceLevelSelected | |
| - } | |
| - overriddenCohortPriceLevel={overriddenCohortPriceLevel} | |
| /> | |
| </> | |
| ); | |
| diff --git a/src/components/SalesScreenComponents/Settings/SalePageSettingsDialog.tsx b/src/components/SalesScreenComponents/Settings/SalePageSettingsDialog.tsx | |
| index aa943f8f..f0caeeb7 100644 | |
| --- a/src/components/SalesScreenComponents/Settings/SalePageSettingsDialog.tsx | |
| +++ b/src/components/SalesScreenComponents/Settings/SalePageSettingsDialog.tsx | |
| @@ -1,6 +1,4 @@ | |
| import { SalesChannelSelector } from "components/navbar/SalesChannelSelector"; | |
| -import { PriceLevelSelect } from "components/PriceLevelSelect"; | |
| -import { Button } from "components/ui/button"; | |
| import { | |
| Dialog, | |
| DialogContent, | |
| @@ -15,10 +13,6 @@ type SalePageSettingsDialogProps = { | |
| onClose: () => void; | |
| selectedSalesChannel?: EntitySalesChannel; | |
| onSalesChannelSelected: (salesChannel: EntitySalesChannel) => void; | |
| - onOverriddenCohortPriceLevelSelected: ( | |
| - priceLevelId: number | undefined, | |
| - ) => void; | |
| - overriddenCohortPriceLevel: number | undefined; | |
| }; | |
| const SalePageSettingsDialog = ({ | |
| @@ -26,52 +20,22 @@ const SalePageSettingsDialog = ({ | |
| onClose, | |
| selectedSalesChannel, | |
| onSalesChannelSelected, | |
| - onOverriddenCohortPriceLevelSelected, | |
| - overriddenCohortPriceLevel, | |
| }: SalePageSettingsDialogProps) => { | |
| const [entity] = useEntitySelected(); | |
| - | |
| return ( | |
| <Dialog open={isOpen} onOpenChange={onClose}> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle>Sale Page Settings</DialogTitle> | |
| </DialogHeader> | |
| - <div className="space-y-4"> | |
| - <div> | |
| - <h3 className="text-sm font-medium mb-2">Sales Channel</h3> | |
| - <SalesChannelSelector | |
| - entityIds={[entity.id]} | |
| - onlyActive | |
| - selectedSalesChannel={selectedSalesChannel} | |
| - onSalesChannelSelected={onSalesChannelSelected} | |
| - /> | |
| - </div> | |
| - <div> | |
| - <h3 className="text-sm font-medium mb-2">Price Level Override</h3> | |
| - <div className="flex items-center space-x-2"> | |
| - <PriceLevelSelect | |
| - value={overriddenCohortPriceLevel as string | undefined} | |
| - onChange={(value) => | |
| - onOverriddenCohortPriceLevelSelected?.( | |
| - value ? Number(value) : undefined, | |
| - ) | |
| - } | |
| - salesChannelId={selectedSalesChannel?.id} | |
| - /> | |
| - {overriddenCohortPriceLevel && ( | |
| - <Button | |
| - variant="outline" | |
| - size="sm" | |
| - onClick={() => | |
| - onOverriddenCohortPriceLevelSelected?.(undefined) | |
| - } | |
| - > | |
| - Clear | |
| - </Button> | |
| - )} | |
| - </div> | |
| - </div> | |
| + <div> | |
| + <h3>Sales Channel</h3> | |
| + <SalesChannelSelector | |
| + entityIds={[entity.id]} | |
| + onlyActive | |
| + selectedSalesChannel={selectedSalesChannel} | |
| + onSalesChannelSelected={onSalesChannelSelected} | |
| + /> | |
| </div> | |
| </DialogContent> | |
| </Dialog> | |
| diff --git a/src/components/SalesScreenComponents/TotalSummaryCard.test.tsx b/src/components/SalesScreenComponents/TotalSummaryCard.test.tsx | |
| deleted file mode 100644 | |
| index a7d40c59..00000000 | |
| --- a/src/components/SalesScreenComponents/TotalSummaryCard.test.tsx | |
| +++ /dev/null | |
| @@ -1,549 +0,0 @@ | |
| -import { fireEvent, render, screen } from "@testing-library/react"; | |
| -import { useSalesContext } from "context/Sales/SalesContext"; | |
| -import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| -import { useEntitySelected } from "src/context/EntityProvider"; | |
| -import { | |
| - createMockSalesContext, | |
| - createMockSalesPaymentContext, | |
| -} from "src/test-utils"; | |
| -import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| -import { useSalePageConfig } from "./SalePageConfigProvider"; | |
| -import { TotalSummaryCard } from "./TotalSummaryCard"; | |
| - | |
| -// Mock all the hooks and dependencies | |
| -vi.mock("context/Sales/SalesContext"); | |
| -vi.mock("context/Sales/SalesPaymentContext"); | |
| -vi.mock("src/context/EntityProvider"); | |
| -vi.mock("./SalePageConfigProvider"); | |
| -vi.mock("components/Auth/PermissionedButton", () => ({ | |
| - PermissionedButton: ({ | |
| - children, | |
| - onClick, | |
| - disabled, | |
| - isLoading, | |
| - colorScheme, | |
| - ...props | |
| - }: any) => ( | |
| - <button | |
| - onClick={onClick} | |
| - disabled={disabled} | |
| - data-loading={isLoading} | |
| - data-color-scheme={colorScheme} | |
| - data-testid="sale-pay-btn" | |
| - {...props} | |
| - > | |
| - {children} | |
| - </button> | |
| - ), | |
| -})); | |
| -vi.mock("../TransactionsComponents/FinishTransactionPaymentModal", () => ({ | |
| - FinishTransacationPaymentModal: () => ( | |
| - <div data-testid="finish-payment-modal" /> | |
| - ), | |
| -})); | |
| - | |
| -const mockUseSalesContext = vi.mocked(useSalesContext); | |
| -const mockUseSalesPaymentContext = vi.mocked(useSalesPaymentContext); | |
| -const mockUseEntitySelected = vi.mocked(useEntitySelected); | |
| -const mockUseSalePageConfig = vi.mocked(useSalePageConfig); | |
| - | |
| -describe("TotalSummaryCard", () => { | |
| - const mockTransactionTotalPrice = vi.fn(); | |
| - const mockReviewTransactionModal = { | |
| - onOpen: vi.fn(), | |
| - onClose: vi.fn(), | |
| - isOpen: false, | |
| - }; | |
| - | |
| - const defaultSalesContext = createMockSalesContext(); | |
| - const defaultSalesPaymentContext = createMockSalesPaymentContext({ | |
| - transactionTotalPrice: mockTransactionTotalPrice, | |
| - reviewTransactionModal: mockReviewTransactionModal, | |
| - }); | |
| - | |
| - const defaultEntity = { id: "entity-1", name: "Test Store" }; | |
| - const defaultSalePageConfig = { overriddenCohortPriceLevel: null }; | |
| - | |
| - beforeEach(() => { | |
| - vi.clearAllMocks(); | |
| - mockUseSalesContext.mockReturnValue(defaultSalesContext as any); | |
| - mockUseSalesPaymentContext.mockReturnValue( | |
| - defaultSalesPaymentContext as any, | |
| - ); | |
| - mockUseEntitySelected.mockReturnValue([defaultEntity, vi.fn()] as any); | |
| - mockUseSalePageConfig.mockReturnValue(defaultSalePageConfig as any); | |
| - | |
| - // Default pricing - same for cash and credit | |
| - mockTransactionTotalPrice.mockImplementation((options) => { | |
| - const paymentMethodId = options?.paymentMethodId; | |
| - if (paymentMethodId === "cash-1") return 10.0; | |
| - if (paymentMethodId === "cc-1") return 10.0; | |
| - return 10.0; // default | |
| - }); | |
| - }); | |
| - | |
| - describe("Pricing Display Logic", () => { | |
| - it("shows single price when cash and credit totals are the same", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 2, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - // Should show single "Pay: $10.00" text | |
| - expect(screen.getByText(/Pay: \$10\.00/)).toBeInTheDocument(); | |
| - | |
| - // Should NOT show cash/credit icons when prices are the same | |
| - const svgElements = document.querySelectorAll('svg[aria-hidden="true"]'); | |
| - expect(svgElements).toHaveLength(0); | |
| - }); | |
| - | |
| - it("shows dual pricing when cash and credit totals differ", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 2, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - // Mock different prices for cash vs credit | |
| - mockTransactionTotalPrice.mockImplementation((options) => { | |
| - const paymentMethodId = options?.paymentMethodId; | |
| - if (paymentMethodId === "cash-1") return 10.0; | |
| - if (paymentMethodId === "cc-1") return 10.5; // Credit has surcharge | |
| - return 10.0; // default | |
| - }); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - // Should show both cash and credit prices in the payment button area | |
| - // Use getAllByText to handle multiple instances and check the payment button specifically | |
| - const cashPrices = screen.getAllByText("$10.00"); | |
| - const creditPrices = screen.getAllByText("$10.50"); | |
| - | |
| - // Should have cash price in subtotal AND payment button | |
| - expect(cashPrices.length).toBeGreaterThanOrEqual(1); | |
| - // Should have credit price in payment button | |
| - expect(creditPrices).toHaveLength(1); | |
| - | |
| - // Should show both icons (SVGs with aria-hidden) | |
| - const svgElements = document.querySelectorAll('svg[aria-hidden="true"]'); | |
| - expect(svgElements).toHaveLength(2); // Cash and credit card icons | |
| - }); | |
| - | |
| - it("calls transactionTotalPrice with correct payment forms", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 2, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - // Should call transactionTotalPrice for cash, credit, and default | |
| - expect(mockTransactionTotalPrice).toHaveBeenCalledWith({ | |
| - paymentMethodId: "cash-1", | |
| - }); | |
| - expect(mockTransactionTotalPrice).toHaveBeenCalledWith({ | |
| - paymentMethodId: "cc-1", | |
| - }); | |
| - expect(mockTransactionTotalPrice).toHaveBeenCalledWith(); // default call | |
| - }); | |
| - | |
| - it("shows loading state when calculating background payment method totals", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 2, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesContext.mockReturnValue({ | |
| - ...defaultSalesContext, | |
| - } as any); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - isCalculatingBackgroundPaymentMethodTotals: true, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - // Should show loading spinner and current price | |
| - expect(screen.getByText(/Pay: \$10\.00/)).toBeInTheDocument(); | |
| - | |
| - // Should show loading spinner (div with animate-spin class) | |
| - const spinner = document.querySelector(".animate-spin"); | |
| - expect(spinner).toBeInTheDocument(); | |
| - }); | |
| - }); | |
| - | |
| - describe("Transaction Totals Calculation", () => { | |
| - it("calculates totals correctly from transaction items", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 10.0, | |
| - quantity: 2, | |
| - discount: 1.0, | |
| - bottleFee: 0.1, | |
| - environmentFee: 0.05, | |
| - tax: 1.5, | |
| - }, | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0.5, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0.4, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - // Subtotal: (10*2 - 1) + (5*1 - 0.5) = 19 + 4.5 = 23.5 | |
| - expect(screen.getByText("$23.50")).toBeInTheDocument(); | |
| - | |
| - // Total Discount: 1.00 + 0.50 = 1.50 (displayed as negative in UI) | |
| - expect(screen.getByText("-$1.50")).toBeInTheDocument(); | |
| - | |
| - // Total Fees: 0.10 + 0.05 + 0 + 0 = 0.15 | |
| - expect(screen.getByText("$0.15")).toBeInTheDocument(); | |
| - | |
| - // Total Tax: 1.50 + 0.40 = 1.90 | |
| - expect(screen.getByText("$1.90")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("handles negative quantities correctly", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 10.0, | |
| - quantity: -1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - // Button should have requires="pos:sell-negative-quantity" permission | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toHaveAttribute("requires", "pos:sell-negative-quantity"); | |
| - }); | |
| - }); | |
| - | |
| - describe("Button States", () => { | |
| - it("disables button when no transaction items", () => { | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems: [], | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toBeDisabled(); | |
| - }); | |
| - | |
| - it("disables button when cart pricing error", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesContext.mockReturnValue({ | |
| - ...defaultSalesContext, | |
| - } as any); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - isGetCartPricingError: true, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toBeDisabled(); | |
| - }); | |
| - | |
| - it("shows loading state when review transaction modal pending", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - reviewTransactionModalPending: true, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toHaveAttribute("data-loading", "true"); | |
| - }); | |
| - | |
| - it("shows loading state when credit card payment pending", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - creditCardPaidPending: true, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toHaveAttribute("data-loading", "true"); | |
| - }); | |
| - | |
| - it("shows green color scheme for positive totals", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockTransactionTotalPrice.mockReturnValue(10.0); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toHaveAttribute("data-color-scheme", "green"); | |
| - }); | |
| - | |
| - it("shows red color scheme for negative totals", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: -2, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockTransactionTotalPrice.mockReturnValue(-10.0); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - expect(button).toHaveAttribute("data-color-scheme", "red"); | |
| - }); | |
| - | |
| - it("opens review transaction modal when clicked", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - const button = screen.getByTestId("sale-pay-btn"); | |
| - fireEvent.click(button); | |
| - | |
| - expect(mockReviewTransactionModal.onOpen).toHaveBeenCalledTimes(1); | |
| - }); | |
| - }); | |
| - | |
| - describe("Price Level Override", () => { | |
| - it("shows price level override warning when overridden", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalePageConfig.mockReturnValue({ | |
| - overriddenCohortPriceLevel: "WHOLESALE", | |
| - } as any); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - expect(screen.getByText("⚠️ Price level overridden")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("does not show price level override warning when not overridden", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 5.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - expect( | |
| - screen.queryByText("⚠️ Price level overridden"), | |
| - ).not.toBeInTheDocument(); | |
| - }); | |
| - }); | |
| - | |
| - describe("Edge Cases", () => { | |
| - it("handles zero totals correctly", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockTransactionTotalPrice.mockReturnValue(0); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - expect(screen.getByText("Pay: $0.00")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("formats large numbers correctly", () => { | |
| - const transactionItems = [ | |
| - { | |
| - price: 1000.0, | |
| - quantity: 1, | |
| - discount: 0, | |
| - bottleFee: 0, | |
| - environmentFee: 0, | |
| - tax: 0, | |
| - }, | |
| - ]; | |
| - | |
| - mockTransactionTotalPrice.mockReturnValue(1234.56); | |
| - | |
| - mockUseSalesPaymentContext.mockReturnValue({ | |
| - ...defaultSalesPaymentContext, | |
| - transactionItems, | |
| - } as any); | |
| - | |
| - render(<TotalSummaryCard />); | |
| - | |
| - expect(screen.getByText("Pay: $1,234.56")).toBeInTheDocument(); | |
| - }); | |
| - }); | |
| -}); | |
| diff --git a/src/components/SalesScreenComponents/TotalSummaryCard.tsx b/src/components/SalesScreenComponents/TotalSummaryCard.tsx | |
| index 8fafa6e1..76fc4a73 100644 | |
| --- a/src/components/SalesScreenComponents/TotalSummaryCard.tsx | |
| +++ b/src/components/SalesScreenComponents/TotalSummaryCard.tsx | |
| @@ -1,32 +1,23 @@ | |
| import { Divider, HStack, Text, VStack, useDisclosure } from "@chakra-ui/react"; | |
| import { PermissionedButton } from "components/Auth/PermissionedButton"; | |
| +import { useSalesContext } from "context/Sales/SalesContext"; | |
| import { useMemo } from "react"; | |
| -import { FaCreditCard, FaMoneyBillWave } from "react-icons/fa"; | |
| -import { useEntitySelected } from "src/context/EntityProvider"; | |
| import { useSalesPaymentContext } from "src/context/Sales/SalesPaymentContext"; | |
| -import { TransactionPaymentForm } from "src/spring-generated"; | |
| -import { currencyFormat, formatPriceAbsolute } from "src/utils/currencyUtils"; | |
| +import { currencyFormat } from "src/utils/currencyUtils"; | |
| import { useDebounceValue } from "usehooks-ts"; | |
| import { FinishTransacationPaymentModal } from "../TransactionsComponents/FinishTransactionPaymentModal"; | |
| -import { useSalePageConfig } from "./SalePageConfigProvider"; | |
| export const TotalSummaryCard = () => { | |
| + const { isGetCartPricingError, isCalculatingCartPrice } = useSalesContext(); | |
| const { | |
| - isGetCartPricingError, | |
| - isCalculatingCartPrice, | |
| - isCalculatingBackgroundPaymentMethodTotals, | |
| - paymentMethodTypeToPaymentMethod, | |
| - findBestPaymentMethod, | |
| transactionTotalPrice, | |
| transactionItems, | |
| reviewTransactionModal, | |
| reviewTransactionModalPending, | |
| creditCardPaidPending, | |
| - salesChannel, | |
| } = useSalesPaymentContext(); | |
| - const [entity] = useEntitySelected(); | |
| - const { overriddenCohortPriceLevel } = useSalePageConfig(); | |
| const finishPaymentDisclosure = useDisclosure(); | |
| + | |
| const totals = useMemo(() => { | |
| return transactionItems.reduce( | |
| (acc, item) => ({ | |
| @@ -63,46 +54,6 @@ export const TotalSummaryCard = () => { | |
| 300, | |
| ); | |
| - // Get cash and credit card totals | |
| - const paymentTotals = useMemo(() => { | |
| - const defaultPaymentMethodId = salesChannel?.defaultPaymentMethodId; | |
| - | |
| - const cashPaymentMethods = | |
| - paymentMethodTypeToPaymentMethod[TransactionPaymentForm.CASH]; | |
| - const cashPaymentMethod = findBestPaymentMethod( | |
| - cashPaymentMethods, | |
| - defaultPaymentMethodId, | |
| - ); | |
| - const cashPaymentMethodId = cashPaymentMethod?.id; | |
| - | |
| - const creditCardPaymentMethods = | |
| - paymentMethodTypeToPaymentMethod[TransactionPaymentForm["CREDIT CARD"]]; | |
| - const creditCardPaymentMethod = findBestPaymentMethod( | |
| - creditCardPaymentMethods, | |
| - defaultPaymentMethodId, | |
| - ); | |
| - const creditCardPaymentMethodId = creditCardPaymentMethod?.id; | |
| - | |
| - const cashTotal = transactionTotalPrice({ | |
| - paymentMethodId: cashPaymentMethodId, | |
| - }); | |
| - const creditCardTotal = transactionTotalPrice({ | |
| - paymentMethodId: creditCardPaymentMethodId, | |
| - }); | |
| - const defaultTotal = transactionTotalPrice(); | |
| - return { | |
| - cash: cashTotal, | |
| - credit: creditCardTotal, | |
| - default: defaultTotal, | |
| - hasSamePrice: Math.abs(cashTotal - creditCardTotal) < 0.01, | |
| - }; | |
| - }, [ | |
| - transactionTotalPrice, | |
| - paymentMethodTypeToPaymentMethod, | |
| - salesChannel?.defaultPaymentMethodId, | |
| - findBestPaymentMethod, | |
| - ]); | |
| - | |
| return ( | |
| <> | |
| <VStack m={2}> | |
| @@ -148,76 +99,13 @@ export const TotalSummaryCard = () => { | |
| debouncedIsCalculatingCartPrice | |
| } | |
| onClick={reviewTransactionModal.onOpen} | |
| - className="w-full min-h-[120px] py-4 px-4 text-3xl" | |
| + className="w-full h-28 text-3xl" | |
| data-testid="sale-pay-btn" | |
| > | |
| - <div className="flex flex-col items-center justify-center h-full w-full gap-4"> | |
| - {/* Price Display with Morphing Container */} | |
| - <div | |
| - className="relative overflow-hidden transition-all duration-300 ease-in-out flex items-center justify-center" | |
| - style={{ | |
| - minWidth: isCalculatingBackgroundPaymentMethodTotals | |
| - ? "300px" | |
| - : paymentTotals.hasSamePrice | |
| - ? "200px" | |
| - : "400px", | |
| - }} | |
| - > | |
| - <div | |
| - className={`flex items-center justify-center transition-all duration-300`} | |
| - > | |
| - {isCalculatingBackgroundPaymentMethodTotals ? ( | |
| - // Loading state - show current price with spinner | |
| - <div className="flex items-center gap-3"> | |
| - <div className="text-3xl font-semibold"> | |
| - {"Pay" + | |
| - (transactionItems?.length > 0 | |
| - ? ": " + formatPriceAbsolute(paymentTotals.default) | |
| - : "")} | |
| - </div> | |
| - <div className="w-5 h-5 border-2 border-current border-t-transparent rounded-full animate-spin" /> | |
| - </div> | |
| - ) : paymentTotals.hasSamePrice ? ( | |
| - // Single price | |
| - <div className="text-3xl font-semibold"> | |
| - {"Pay" + | |
| - (transactionItems?.length > 0 | |
| - ? ": " + formatPriceAbsolute(paymentTotals.default) | |
| - : "")} | |
| - </div> | |
| - ) : ( | |
| - // Dual price with smooth entrance | |
| - <div className="flex items-center gap-8 animate-in fade-in duration-300"> | |
| - {/* Cash Price */} | |
| - <div className="flex items-center gap-3"> | |
| - <FaMoneyBillWave className="w-6 h-6" aria-hidden="true" /> | |
| - <div className="text-3xl font-semibold"> | |
| - {formatPriceAbsolute(paymentTotals.cash)} | |
| - </div> | |
| - </div> | |
| - | |
| - {/* Separator */} | |
| - <div className="w-px h-8 bg-current opacity-30" /> | |
| - | |
| - {/* Credit Price */} | |
| - <div className="flex items-center gap-3"> | |
| - <FaCreditCard className="w-6 h-6" aria-hidden="true" /> | |
| - <div className="text-3xl font-semibold"> | |
| - {formatPriceAbsolute(paymentTotals.credit)} | |
| - </div> | |
| - </div> | |
| - </div> | |
| - )} | |
| - </div> | |
| - </div> | |
| - | |
| - {/* Price Level Override Note */} | |
| - {overriddenCohortPriceLevel && ( | |
| - <div className="text-sm opacity-90 text-center"> | |
| - ⚠️ Price level overridden | |
| - </div> | |
| - )} | |
| - </div> | |
| + Pay | |
| + {transactionItems.length > 0 | |
| + ? `: ${currencyFormat("USD", transactionTotalPrice())}` | |
| + : ""} | |
| </PermissionedButton> | |
| </VStack> | |
| <FinishTransacationPaymentModal {...finishPaymentDisclosure} /> | |
| diff --git a/src/components/SubscriptionBanner.tsx b/src/components/SubscriptionBanner.tsx | |
| deleted file mode 100644 | |
| index 31f7fda7..00000000 | |
| --- a/src/components/SubscriptionBanner.tsx | |
| +++ /dev/null | |
| @@ -1,40 +0,0 @@ | |
| -import { AlertTriangle } from "lucide-react"; | |
| -import { useNavigate } from "react-router-dom"; | |
| -import { Button } from "./ui/button"; | |
| -import { Card, CardContent } from "./ui/card"; | |
| - | |
| -export const SubscriptionBanner = ({ | |
| - disablePayNow, | |
| -}: { | |
| - disablePayNow: boolean; | |
| -}) => { | |
| - const navigate = useNavigate(); | |
| - | |
| - const handlePayNow = () => { | |
| - navigate("/settings/?tab=about-store"); | |
| - }; | |
| - | |
| - return ( | |
| - <div className="fixed top-8 left-1/2 transform -translate-x-1/2 z-50 max-w-md"> | |
| - <Card className="border-red-200 bg-red-50 shadow-xl"> | |
| - <CardContent className="p-3"> | |
| - <div className="flex items-center gap-2"> | |
| - <AlertTriangle className="h-4 w-4 text-red-600 flex-shrink-0" /> | |
| - <p className="text-sm text-red-700 leading-relaxed flex-1"> | |
| - Your subscription payment is overdue. | |
| - </p> | |
| - <Button | |
| - onClick={handlePayNow} | |
| - variant="default" | |
| - size="sm" | |
| - className="bg-red-500 hover:bg-red-400 text-white font-semibold shadow-md hover:shadow-lg transition-all duration-200 rounded-lg px-4 py-0.5 text-sm h-6" | |
| - disabled={disablePayNow} | |
| - > | |
| - Pay | |
| - </Button> | |
| - </div> | |
| - </CardContent> | |
| - </Card> | |
| - </div> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SubscriptionBannerWrapper.tsx b/src/components/SubscriptionBannerWrapper.tsx | |
| deleted file mode 100644 | |
| index f36111af..00000000 | |
| --- a/src/components/SubscriptionBannerWrapper.tsx | |
| +++ /dev/null | |
| @@ -1,58 +0,0 @@ | |
| -import { useEntity } from "context/EntityProvider"; | |
| -import { usePermissions } from "context/PermissionsContext"; | |
| -import { useMemo } from "react"; | |
| -import { useGetEntitySubscriptionStatus } from "src/spring-generated/hooks/useGetEntitySubscriptionStatus"; | |
| -import { SubscriptionBanner } from "./SubscriptionBanner"; | |
| - | |
| -const badSubscriptionStatuses = new Set([ | |
| - "past_due", | |
| - "unpaid", | |
| - "incomplete", | |
| - "incomplete_expired", | |
| -]); | |
| - | |
| -export const SubscriptionBannerWrapper = () => { | |
| - const [entity] = useEntity(); | |
| - const { hasPermission } = usePermissions(); | |
| - const hasSubscriptionReadStatusPermission = | |
| - hasPermission("esub/*:read_status"); | |
| - const hasSubscriptionReadPaymentLinkPermission = hasPermission( | |
| - "esub/*:read_payment_link", | |
| - ); | |
| - const { data: subscriptionStatus } = useGetEntitySubscriptionStatus( | |
| - { | |
| - entityId: entity?.id ?? 0, | |
| - }, | |
| - { | |
| - query: { | |
| - enabled: !!entity?.id && hasSubscriptionReadStatusPermission, | |
| - queryKey: ["entitySubscriptionStatus", entity?.id], | |
| - throwOnError: false, | |
| - }, | |
| - }, | |
| - ); | |
| - | |
| - // Determine if subscription is unpaid | |
| - const isSubscriptionUnpaid = useMemo( | |
| - () => | |
| - subscriptionStatus && | |
| - badSubscriptionStatuses.has(subscriptionStatus.toLowerCase()), | |
| - [subscriptionStatus], | |
| - ); | |
| - | |
| - const shouldShowBanner = useMemo( | |
| - () => | |
| - isSubscriptionUnpaid && entity?.id && hasSubscriptionReadStatusPermission, | |
| - [isSubscriptionUnpaid, entity?.id, hasSubscriptionReadStatusPermission], | |
| - ); | |
| - | |
| - if (!shouldShowBanner) { | |
| - return null; | |
| - } | |
| - | |
| - return ( | |
| - <SubscriptionBanner | |
| - disablePayNow={!hasSubscriptionReadPaymentLinkPermission} | |
| - /> | |
| - ); | |
| -}; | |
| diff --git a/src/components/SubscriptionStatusBadge.tsx b/src/components/SubscriptionStatusBadge.tsx | |
| deleted file mode 100644 | |
| index c4bf5a2f..00000000 | |
| --- a/src/components/SubscriptionStatusBadge.tsx | |
| +++ /dev/null | |
| @@ -1,104 +0,0 @@ | |
| -import { cn } from "../lib/utils"; | |
| -import { Badge } from "./ui/badge"; | |
| - | |
| -type SubscriptionStatus = | |
| - | "incomplete" | |
| - | "incomplete_expired" | |
| - | "trialing" | |
| - | "active" | |
| - | "past_due" | |
| - | "canceled" | |
| - | "unpaid" | |
| - | "paused"; | |
| - | |
| -interface SubscriptionStatusBadgeProps { | |
| - status: SubscriptionStatus | string; | |
| - className?: string; | |
| -} | |
| - | |
| -const getStatusConfig = (status: string) => { | |
| - const normalizedStatus = status.toLowerCase(); | |
| - | |
| - switch (normalizedStatus) { | |
| - case "active": | |
| - return { | |
| - label: "Active", | |
| - variant: "default" as const, | |
| - className: | |
| - "bg-green-100 text-green-800 border-green-200 hover:bg-green-200", | |
| - }; | |
| - case "trialing": | |
| - return { | |
| - label: "Trialing", | |
| - variant: "secondary" as const, | |
| - className: | |
| - "bg-blue-100 text-blue-800 border-blue-200 hover:bg-blue-200", | |
| - }; | |
| - case "past_due": | |
| - return { | |
| - label: "Past Due", | |
| - variant: "destructive" as const, | |
| - className: "bg-red-100 text-red-800 border-red-200 hover:bg-red-200", | |
| - }; | |
| - case "unpaid": | |
| - return { | |
| - label: "Unpaid", | |
| - variant: "destructive" as const, | |
| - className: "bg-red-100 text-red-800 border-red-200 hover:bg-red-200", | |
| - }; | |
| - case "incomplete": | |
| - return { | |
| - label: "Incomplete", | |
| - variant: "outline" as const, | |
| - className: | |
| - "bg-yellow-100 text-yellow-800 border-yellow-200 hover:bg-yellow-200", | |
| - }; | |
| - case "incomplete_expired": | |
| - return { | |
| - label: "Incomplete Expired", | |
| - variant: "destructive" as const, | |
| - className: "bg-red-100 text-red-800 border-red-200 hover:bg-red-200", | |
| - }; | |
| - case "canceled": | |
| - return { | |
| - label: "Canceled", | |
| - variant: "secondary" as const, | |
| - className: | |
| - "bg-gray-100 text-gray-800 border-gray-200 hover:bg-gray-200", | |
| - }; | |
| - case "paused": | |
| - return { | |
| - label: "Paused", | |
| - variant: "outline" as const, | |
| - className: | |
| - "bg-orange-100 text-orange-800 border-orange-200 hover:bg-orange-200", | |
| - }; | |
| - default: | |
| - return { | |
| - label: status, | |
| - variant: "outline" as const, | |
| - className: | |
| - "bg-gray-100 text-gray-600 border-gray-200 hover:bg-gray-200", | |
| - }; | |
| - } | |
| -}; | |
| - | |
| -export const SubscriptionStatusBadge = ({ | |
| - status, | |
| - className, | |
| -}: SubscriptionStatusBadgeProps) => { | |
| - const config = getStatusConfig(status); | |
| - | |
| - return ( | |
| - <Badge | |
| - variant={config.variant} | |
| - className={cn( | |
| - "font-medium text-xs px-2 py-1 border", | |
| - config.className, | |
| - className, | |
| - )} | |
| - > | |
| - {config.label} | |
| - </Badge> | |
| - ); | |
| -}; | |
| diff --git a/src/components/Table/AddRow/AddRow.tsx b/src/components/Table/AddRow/AddRow.tsx | |
| index 6272ab4b..e292f99a 100644 | |
| --- a/src/components/Table/AddRow/AddRow.tsx | |
| +++ b/src/components/Table/AddRow/AddRow.tsx | |
| @@ -37,17 +37,14 @@ export function AddRow<Data>({ | |
| if (newRow) { | |
| const onMouseEnter = () => setIsHovering(true); | |
| const onMouseLeave = () => setIsHovering(false); | |
| - const currentPortalRef = portalRef.current; | |
| - currentPortalRef.addEventListener("mouseenter", onMouseEnter); | |
| - currentPortalRef.addEventListener("mouseleave", onMouseLeave); | |
| + portalRef.current.addEventListener("mouseenter", onMouseEnter); | |
| + portalRef.current.addEventListener("mouseleave", onMouseLeave); | |
| return () => { | |
| - currentPortalRef.removeEventListener("mouseenter", onMouseEnter); | |
| - currentPortalRef.removeEventListener("mouseleave", onMouseLeave); | |
| + portalRef.current?.removeEventListener("mouseenter", onMouseEnter); | |
| + portalRef.current?.removeEventListener("mouseleave", onMouseLeave); | |
| }; | |
| } | |
| - | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [portalRef?.current, newRow]); | |
| return ( | |
| diff --git a/src/components/TagSummary.tsx b/src/components/TagSummary.tsx | |
| index cdefa2f6..5f5b99fe 100644 | |
| --- a/src/components/TagSummary.tsx | |
| +++ b/src/components/TagSummary.tsx | |
| @@ -170,7 +170,6 @@ const TagSummary = ({ | |
| ), | |
| }), | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [hasPermission, isPrinting], | |
| ); | |
| diff --git a/src/components/TransactionByDate.tsx b/src/components/TransactionByDate.tsx | |
| index fcf054b6..3b4b2ac0 100644 | |
| --- a/src/components/TransactionByDate.tsx | |
| +++ b/src/components/TransactionByDate.tsx | |
| @@ -135,7 +135,6 @@ const TransactionByDate = ({ | |
| ), | |
| }), | |
| ]; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| totals?.bottleDeposit, | |
| totals?.discount, | |
| diff --git a/src/components/TransactionDetail/DecisionDetailsDrawer.tsx b/src/components/TransactionDetail/DecisionDetailsDrawer.tsx | |
| deleted file mode 100644 | |
| index 61797b1e..00000000 | |
| --- a/src/components/TransactionDetail/DecisionDetailsDrawer.tsx | |
| +++ /dev/null | |
| @@ -1,145 +0,0 @@ | |
| -import { Badge } from "components/ui/badge"; | |
| -import { Button } from "components/ui/button"; | |
| -import { | |
| - Drawer, | |
| - DrawerClose, | |
| - DrawerContent, | |
| - DrawerDescription, | |
| - DrawerFooter, | |
| - DrawerHeader, | |
| - DrawerTitle, | |
| -} from "components/ui/drawer"; | |
| -import { useUserAuth } from "context/AuthenticationContext/AuthenticationContext"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { useRegisterProvider } from "context/RegisterProvider"; | |
| -import { useOrderItemDecisionUpdater } from "hooks/useOrderItemDecisionUpdater"; | |
| -import { DbOrderItemDecision } from "src/phoenix-generated"; | |
| - | |
| -interface DecisionDetailsDrawerProps { | |
| - isOpen: boolean; | |
| - onClose: () => void; | |
| - decision: DbOrderItemDecision | null; | |
| - onDecisionUpdated?: () => void; | |
| -} | |
| - | |
| -const getDecisionStatusBadge = (status: string) => { | |
| - switch (status.toUpperCase()) { | |
| - case "ACCEPTED": | |
| - return <Badge variant="successful">Accepted</Badge>; | |
| - case "REJECTED": | |
| - return <Badge variant="destructive">Rejected</Badge>; | |
| - case "CREATED": | |
| - return <Badge variant="pending">Pending</Badge>; | |
| - default: | |
| - return <Badge variant="outline">{status}</Badge>; | |
| - } | |
| -}; | |
| - | |
| -export const DecisionDetailsDrawer: React.FC<DecisionDetailsDrawerProps> = ({ | |
| - isOpen, | |
| - onClose, | |
| - decision, | |
| - onDecisionUpdated, | |
| -}) => { | |
| - const { user } = useUserAuth(); | |
| - const [entity] = useEntitySelected(); | |
| - const { register } = useRegisterProvider(); | |
| - const { updateDecisions, isUpdating } = useOrderItemDecisionUpdater({ | |
| - onSuccess: () => { | |
| - onDecisionUpdated?.(); | |
| - onClose(); | |
| - }, | |
| - }); | |
| - | |
| - const handleStatusUpdate = async (status: "ACCEPTED" | "REJECTED") => { | |
| - if (!decision || !user?.uid) return; | |
| - | |
| - await updateDecisions([ | |
| - { | |
| - decisionId: decision.id, | |
| - status, | |
| - userId: user?.uid, | |
| - source: `${entity.id.toString()} register:${register.registerNumber?.toString() ?? "unknown"}`, | |
| - }, | |
| - ]); | |
| - }; | |
| - | |
| - if (!decision) return null; | |
| - | |
| - const isPending = decision.status.toUpperCase() === "CREATED"; | |
| - const metadata = decision.metadata; | |
| - const notes = metadata?.customerNotes || metadata?.internalNotes; | |
| - | |
| - return ( | |
| - <Drawer open={isOpen} onOpenChange={(open) => !open && onClose()}> | |
| - <DrawerContent> | |
| - <DrawerHeader> | |
| - <DrawerTitle>Decision Details</DrawerTitle> | |
| - <DrawerDescription> | |
| - Transaction Item ID: {decision.transactionItemId} | |
| - </DrawerDescription> | |
| - </DrawerHeader> | |
| - | |
| - <div className="px-4 space-y-4"> | |
| - <div className="flex items-center gap-2"> | |
| - <span className="font-medium">Status:</span> | |
| - {getDecisionStatusBadge(decision.status)} | |
| - </div> | |
| - | |
| - <div className="flex items-center gap-2"> | |
| - <span className="font-medium">Decision Time:</span> | |
| - <span> | |
| - {decision.decisionTime | |
| - ? new Date(decision.decisionTime).toLocaleString() | |
| - : "-"} | |
| - </span> | |
| - </div> | |
| - | |
| - {decision.reason && ( | |
| - <div className="space-y-1"> | |
| - <span className="font-medium">Reason:</span> | |
| - <p className="text-sm text-gray-600">{decision.reason}</p> | |
| - </div> | |
| - )} | |
| - | |
| - {notes && ( | |
| - <div className="space-y-1"> | |
| - <span className="font-medium">Notes:</span> | |
| - <p className="text-sm text-gray-600">{notes}</p> | |
| - </div> | |
| - )} | |
| - </div> | |
| - | |
| - <DrawerFooter> | |
| - <div className="flex gap-2"> | |
| - {isPending && ( | |
| - <> | |
| - <Button | |
| - variant="outline" | |
| - disabled={isUpdating} | |
| - onClick={() => handleStatusUpdate("ACCEPTED")} | |
| - className="flex-1" | |
| - > | |
| - Accept | |
| - </Button> | |
| - <Button | |
| - variant="destructive" | |
| - disabled={isUpdating} | |
| - onClick={() => handleStatusUpdate("REJECTED")} | |
| - className="flex-1" | |
| - > | |
| - Reject | |
| - </Button> | |
| - </> | |
| - )} | |
| - <DrawerClose asChild> | |
| - <Button variant="secondary" className="flex-1"> | |
| - Close | |
| - </Button> | |
| - </DrawerClose> | |
| - </div> | |
| - </DrawerFooter> | |
| - </DrawerContent> | |
| - </Drawer> | |
| - ); | |
| -}; | |
| diff --git a/src/components/TransactionDetail/TransactionItemsTable.tsx b/src/components/TransactionDetail/TransactionItemsTable.tsx | |
| index ba4046cc..d875527c 100644 | |
| --- a/src/components/TransactionDetail/TransactionItemsTable.tsx | |
| +++ b/src/components/TransactionDetail/TransactionItemsTable.tsx | |
| @@ -1,110 +1,28 @@ | |
| import { createColumnHelper } from "@tanstack/react-table"; | |
| import { TransformityDataTable } from "components/Table/TransformityDataTable"; | |
| -import { Badge } from "components/ui/badge"; | |
| -import { Button } from "components/ui/button"; | |
| import { Popover, PopoverContent, PopoverTrigger } from "components/ui/popover"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| import { usePermissions } from "context/PermissionsContext"; | |
| import { TransactionDataOutput } from "generated/types"; | |
| import { TriangleAlert } from "lucide-react"; | |
| -import { useMemo, useState } from "react"; | |
| +import { useMemo } from "react"; | |
| import { Link } from "react-router-dom"; | |
| -import { DbOrderItemDecision } from "src/phoenix-generated"; | |
| import { currencyFormat } from "utils/currencyUtils"; | |
| -import { DecisionDetailsDrawer } from "./DecisionDetailsDrawer"; | |
| interface TransactionItemsTableProps { | |
| items: TransactionDataOutput[]; | |
| - orderItemDecisions?: DbOrderItemDecision[]; | |
| - selectedRows?: Set<number>; | |
| - onRowSelect?: (itemId: number, isSelected: boolean) => void; | |
| - onSelectAll?: (isSelected: boolean) => void; | |
| - onDecisionUpdated?: () => void; | |
| } | |
| const columnHelper = createColumnHelper<TransactionDataOutput>(); | |
| -const getDecisionStatusBadge = (status: string) => { | |
| - switch (status.toUpperCase()) { | |
| - case "ACCEPTED": | |
| - return <Badge variant="successful">Accepted</Badge>; | |
| - case "REJECTED": | |
| - return <Badge variant="destructive">Rejected</Badge>; | |
| - case "CREATED": | |
| - return <Badge variant="pending">Pending</Badge>; | |
| - default: | |
| - return <Badge variant="outline">{status}</Badge>; | |
| - } | |
| -}; | |
| - | |
| export const TransactionItemsTable = ({ | |
| items, | |
| - orderItemDecisions = [], | |
| - selectedRows = new Set(), | |
| - onRowSelect, | |
| - onSelectAll, | |
| - onDecisionUpdated, | |
| }: TransactionItemsTableProps) => { | |
| const [entity] = useEntitySelected(); | |
| const { hasPermission } = usePermissions(); | |
| - const [selectedDecision, setSelectedDecision] = | |
| - useState<DbOrderItemDecision | null>(null); | |
| - const [isDrawerOpen, setIsDrawerOpen] = useState(false); | |
| - | |
| - // Create a map for quick lookup of decisions by transaction item ID | |
| - const decisionMap = useMemo(() => { | |
| - const map = new Map<number, DbOrderItemDecision>(); | |
| - orderItemDecisions.forEach((decision) => { | |
| - map.set(decision.transactionItemId, decision); | |
| - }); | |
| - return map; | |
| - }, [orderItemDecisions]); | |
| - | |
| - const hasOrderDecisions = orderItemDecisions.length > 0; | |
| - const handleDecisionClick = (decision: DbOrderItemDecision) => { | |
| - setSelectedDecision(decision); | |
| - setIsDrawerOpen(true); | |
| - }; | |
| - | |
| - const handleDrawerClose = () => { | |
| - setIsDrawerOpen(false); | |
| - setSelectedDecision(null); | |
| - }; | |
| - | |
| - const columns = useMemo( | |
| - () => [ | |
| - // Add checkbox column if there are order decisions | |
| - ...(hasOrderDecisions && onRowSelect | |
| - ? [ | |
| - columnHelper.display({ | |
| - id: "select", | |
| - header: () => ( | |
| - <input | |
| - type="checkbox" | |
| - checked={ | |
| - selectedRows.size === items.length && items.length > 0 | |
| - } | |
| - onChange={(e) => { | |
| - const isSelected = e.target.checked; | |
| - onSelectAll?.(isSelected); | |
| - }} | |
| - className="rounded border-gray-300" | |
| - /> | |
| - ), | |
| - cell: ({ row }) => ( | |
| - <input | |
| - type="checkbox" | |
| - checked={selectedRows.has(row.original.id)} | |
| - onChange={(e) => { | |
| - onRowSelect(row.original.id, e.target.checked); | |
| - }} | |
| - className="rounded border-gray-300" | |
| - /> | |
| - ), | |
| - }), | |
| - ] | |
| - : []), | |
| + const columns = useMemo(() => { | |
| + const cols = [ | |
| columnHelper.accessor("name", { | |
| cell: ({ row, getValue }) => ( | |
| <Link | |
| @@ -158,72 +76,34 @@ export const TransactionItemsTable = ({ | |
| header: "Item total", | |
| cell: ({ getValue }) => currencyFormat("USD", getValue()), | |
| }), | |
| - ...(hasPermission("item/*:stats", [entity.id]) | |
| - ? [ | |
| - columnHelper.accessor("grossProfit", { | |
| - header: "Profit margin", | |
| - cell: ({ getValue }) => { | |
| - const value = getValue(); | |
| - return value ? (value * 100).toFixed(2) + "%" : "-"; | |
| - }, | |
| - }), | |
| - ] | |
| - : []), | |
| - ...(hasOrderDecisions && onRowSelect && onSelectAll | |
| - ? [ | |
| - columnHelper.display({ | |
| - id: "decisionStatus", | |
| - header: "Decision", | |
| - cell: ({ row }) => { | |
| - const decision = decisionMap.get(row.original.id); | |
| - if (!decision) return null; | |
| + ]; | |
| - return ( | |
| - <div className="flex items-center gap-2"> | |
| - {getDecisionStatusBadge(decision.status)} | |
| - <Button | |
| - variant="outline" | |
| - size="sm" | |
| - onClick={() => handleDecisionClick(decision)} | |
| - > | |
| - View Details | |
| - </Button> | |
| - </div> | |
| - ); | |
| - }, | |
| - }), | |
| - ] | |
| - : []), | |
| - ], | |
| - [ | |
| - hasOrderDecisions, | |
| - onRowSelect, | |
| - onSelectAll, | |
| - hasPermission, | |
| - entity.id, | |
| - selectedRows, | |
| - items.length, | |
| - decisionMap, | |
| - ], | |
| - ); | |
| + if (hasPermission("item/*:stats", [entity.id])) { | |
| + cols.splice( | |
| + 5, | |
| + 0, | |
| + columnHelper.accessor("grossProfit", { | |
| + header: "Profit margin", | |
| + cell: ({ getValue }) => { | |
| + const value = getValue(); | |
| + return value ? (value * 100).toFixed(2) + "%" : "-"; | |
| + }, | |
| + }) as unknown as any, | |
| + ); | |
| + } | |
| + | |
| + return cols; | |
| + }, [entity.id, hasPermission]); | |
| return ( | |
| - <> | |
| - <TransformityDataTable | |
| - data={items} | |
| - columns={columns} | |
| - containerProps={{ | |
| - width: "100%", | |
| - }} | |
| - variant="pretty" | |
| - isV2Header | |
| - /> | |
| - <DecisionDetailsDrawer | |
| - isOpen={isDrawerOpen} | |
| - onClose={handleDrawerClose} | |
| - decision={selectedDecision} | |
| - onDecisionUpdated={onDecisionUpdated} | |
| - /> | |
| - </> | |
| + <TransformityDataTable | |
| + data={items} | |
| + columns={columns} | |
| + containerProps={{ | |
| + width: "100%", | |
| + }} | |
| + variant="pretty" | |
| + isV2Header | |
| + /> | |
| ); | |
| }; | |
| diff --git a/src/components/TransactionsComponents/useTransactionReceipt.tsx b/src/components/TransactionsComponents/useTransactionReceipt.tsx | |
| index b4a8a2f0..c9bd258e 100644 | |
| --- a/src/components/TransactionsComponents/useTransactionReceipt.tsx | |
| +++ b/src/components/TransactionsComponents/useTransactionReceipt.tsx | |
| @@ -58,10 +58,6 @@ export const useTransactionReceipt = () => { | |
| EntityConfigKey.RECEIPT_BOTTOM_TEXT, | |
| "", | |
| ); | |
| - const { value: showCashierOnReceipt } = useEntityConfig( | |
| - EntityConfigKey.SHOW_CASHIER_ON_RECEIPT, | |
| - true, | |
| - ); | |
| const downloadAssetLinkMutation = useGetDownloadAssetLink(); | |
| const printReceipt = useCallback( | |
| @@ -98,7 +94,7 @@ export const useTransactionReceipt = () => { | |
| ); | |
| const receiptJSX = shortReceiptConfig ? ( | |
| - <Printer width={printerWidth} className="mx-auto" type="star"> | |
| + <Printer width={printerWidth} type="star"> | |
| {logoUrl && ( | |
| <Image crossOrigin="anonymous" src={logoUrl} align="center" /> | |
| )} | |
| @@ -163,14 +159,12 @@ export const useTransactionReceipt = () => { | |
| : "UNKNOWN"} | |
| </Text> | |
| )} | |
| - {showCashierOnReceipt && ( | |
| - <Text align="center"> | |
| - CASHIER:{" "} | |
| - {transactionOutput.completedByName | |
| - ? `${transactionOutput.completedByName.split(" ")?.[0]}` | |
| - : `-`} | |
| - </Text> | |
| - )} | |
| + <Text> | |
| + CASHIER:{" "} | |
| + {transactionOutput.completedByName | |
| + ? `${transactionOutput.completedByName.split(" ")?.[0]}` | |
| + : `-`} | |
| + </Text> | |
| {transactionOutput.transactionItems.map((itemDetail, index) => { | |
| return ( | |
| <Fragment key={index}> | |
| @@ -292,13 +286,22 @@ export const useTransactionReceipt = () => { | |
| )} | |
| /> | |
| )} | |
| + {entity.surchargeFee && !!transactionOutput.creditCardFee && ( | |
| + <Row | |
| + left="PAYMENT PROCESSING FEE:" | |
| + right={USDollar.format(transactionOutput.creditCardFee)} | |
| + /> | |
| + )} | |
| <Row | |
| left={"TOTAL"} | |
| right={USDollar.format( | |
| transactionOutput.transactionItems.reduce( | |
| (prev, a) => prev + a.totalPrice, | |
| 0, | |
| - ), | |
| + ) + | |
| + (entity.surchargeFee | |
| + ? (transactionOutput.creditCardFee ?? 0) | |
| + : 0), | |
| )} | |
| /> | |
| <Line /> | |
| @@ -442,7 +445,7 @@ export const useTransactionReceipt = () => { | |
| <Cut /> | |
| </Printer> | |
| ) : ( | |
| - <Printer width={printerWidth} className="mx-auto" type="star"> | |
| + <Printer width={printerWidth} type="star"> | |
| {entity.id === 12 && ( | |
| <Image src="https://store-logos-public-prod.s3.amazonaws.com/Contislogo.png" /> | |
| )} | |
| @@ -512,14 +515,6 @@ export const useTransactionReceipt = () => { | |
| : "UNKNOWN"} | |
| </Text> | |
| )} | |
| - {showCashierOnReceipt && ( | |
| - <Text align="center"> | |
| - CASHIER:{" "} | |
| - {transactionOutput.completedByName | |
| - ? `${transactionOutput.completedByName.split(" ")?.[0]}` | |
| - : `-`} | |
| - </Text> | |
| - )} | |
| {transactionOutput.transactionItems.map((itemDetail, index) => { | |
| return ( | |
| <Fragment key={index}> | |
| @@ -739,21 +734,18 @@ export const useTransactionReceipt = () => { | |
| void sendReceiptData(receiptJSX); | |
| }, | |
| [ | |
| - queryClient, | |
| - loyaltyProgramId, | |
| - downloadAssetLinkMutation, | |
| - receiptLogo, | |
| + departmentKeyMap, | |
| + entity.address, | |
| entity.id, | |
| entity.name, | |
| - entity.address, | |
| entity.phoneNumber, | |
| - logoUrlFallback, | |
| - shortReceiptConfig, | |
| + loyaltyProgramId, | |
| printerWidth, | |
| - showCashierOnReceipt, | |
| + queryClient, | |
| receiptBottomText, | |
| sendReceiptData, | |
| - departmentKeyMap, | |
| + shortReceiptConfig, | |
| + entity.surchargeFee, | |
| ], | |
| ); | |
| diff --git a/src/components/UnauthenticatedUserOnlyRoute.tsx b/src/components/UnauthenticatedUserOnlyRoute.tsx | |
| index ec9b0483..af81a4e6 100644 | |
| --- a/src/components/UnauthenticatedUserOnlyRoute.tsx | |
| +++ b/src/components/UnauthenticatedUserOnlyRoute.tsx | |
| @@ -1,9 +1,9 @@ | |
| import { useUserAuth } from "context/AuthenticationContext/AuthenticationContext"; | |
| -import type { FC } from "react"; | |
| +import React from "react"; | |
| import { Navigate, Outlet } from "react-router-dom"; | |
| import Loading from "./Loading"; | |
| -const UnauthenticatedUserOnlyRoute: FC = () => { | |
| +const UnauthenticatedUserOnlyRoute: React.FC<{}> = () => { | |
| const { user } = useUserAuth(); | |
| if (user === undefined) { | |
| @@ -11,7 +11,7 @@ const UnauthenticatedUserOnlyRoute: FC = () => { | |
| } else if (user === null) { | |
| return <Outlet />; | |
| } else { | |
| - return <Navigate to="/register/open/" />; | |
| + return <Navigate to="/sale/" />; | |
| } | |
| }; | |
| diff --git a/src/components/__tests__/DatabaseSyncLoader.test.tsx b/src/components/__tests__/DatabaseSyncLoader.test.tsx | |
| deleted file mode 100644 | |
| index 5f6b4cbe..00000000 | |
| --- a/src/components/__tests__/DatabaseSyncLoader.test.tsx | |
| +++ /dev/null | |
| @@ -1,179 +0,0 @@ | |
| -import { act, render, screen } from "@testing-library/react"; | |
| -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; | |
| -import { DatabaseSyncLoader } from "../DatabaseSyncLoader"; | |
| - | |
| -// Mock the cn utility function | |
| -vi.mock("../lib/utils", () => ({ | |
| - cn: vi.fn((...classes) => classes.filter(Boolean).join(" ")), | |
| -})); | |
| - | |
| -describe("DatabaseSyncLoader", () => { | |
| - beforeEach(() => { | |
| - vi.clearAllMocks(); | |
| - // Mock timers for testing animations | |
| - vi.useFakeTimers(); | |
| - }); | |
| - | |
| - afterEach(() => { | |
| - vi.useRealTimers(); | |
| - }); | |
| - | |
| - it("should render with default props", () => { | |
| - render(<DatabaseSyncLoader />); | |
| - | |
| - expect(screen.getByText(/Syncing database/)).toBeInTheDocument(); | |
| - expect( | |
| - screen.getByText("Please wait while we prepare your data"), | |
| - ).toBeInTheDocument(); | |
| - expect(screen.getByText("Transformity Database")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should render with custom message", () => { | |
| - const customMessage = "Loading inventory data"; | |
| - render(<DatabaseSyncLoader message={customMessage} />); | |
| - | |
| - expect(screen.getByText(customMessage)).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should show progress bar when showProgress is true", () => { | |
| - render(<DatabaseSyncLoader showProgress={true} />); | |
| - | |
| - expect(screen.getByText("Syncing")).toBeInTheDocument(); | |
| - expect(screen.getByText("0%")).toBeInTheDocument(); | |
| - | |
| - // Progress bar container should be present | |
| - const progressContainer = screen.getByText("Syncing").closest("div"); | |
| - expect(progressContainer).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should not show progress bar when showProgress is false", () => { | |
| - render(<DatabaseSyncLoader showProgress={false} />); | |
| - | |
| - expect(screen.queryByText("Syncing")).not.toBeInTheDocument(); | |
| - expect(screen.queryByText("0%")).not.toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should animate dots in loading text", () => { | |
| - render(<DatabaseSyncLoader message="Loading" />); | |
| - | |
| - // Initially no dots | |
| - expect(screen.getByText("Loading")).toBeInTheDocument(); | |
| - | |
| - // After 500ms, should have one dot | |
| - act(() => { | |
| - vi.advanceTimersByTime(500); | |
| - }); | |
| - expect(screen.getByText("Loading.")).toBeInTheDocument(); | |
| - | |
| - // After another 500ms, should have two dots | |
| - act(() => { | |
| - vi.advanceTimersByTime(500); | |
| - }); | |
| - expect(screen.getByText("Loading..")).toBeInTheDocument(); | |
| - | |
| - // After another 500ms, should have three dots | |
| - act(() => { | |
| - vi.advanceTimersByTime(500); | |
| - }); | |
| - expect(screen.getByText("Loading...")).toBeInTheDocument(); | |
| - | |
| - // After another 500ms, should reset to no dots | |
| - act(() => { | |
| - vi.advanceTimersByTime(500); | |
| - }); | |
| - expect(screen.getByText("Loading")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should animate progress bar when showProgress is true", () => { | |
| - render(<DatabaseSyncLoader showProgress={true} />); | |
| - | |
| - // Initially 0% | |
| - expect(screen.getByText("0%")).toBeInTheDocument(); | |
| - | |
| - // After 3000ms, progress should increase (matches the interval in component) | |
| - act(() => { | |
| - vi.advanceTimersByTime(3000); | |
| - }); | |
| - | |
| - // Progress should be greater than 0 but less than or equal to 90 | |
| - const progressText = screen.getByText(/%$/); | |
| - const progressValue = parseInt( | |
| - progressText.textContent?.replace("%", "") || "0", | |
| - ); | |
| - expect(progressValue).toBeGreaterThan(0); | |
| - expect(progressValue).toBeLessThanOrEqual(90); | |
| - }); | |
| - | |
| - it("should cap progress at 90%", () => { | |
| - render(<DatabaseSyncLoader showProgress={true} />); | |
| - | |
| - // Advance time significantly to reach the cap | |
| - act(() => { | |
| - vi.advanceTimersByTime(10000); // 10 seconds | |
| - }); | |
| - | |
| - const progressText = screen.getByText(/%$/); | |
| - const progressValue = parseInt( | |
| - progressText.textContent?.replace("%", "") || "0", | |
| - ); | |
| - expect(progressValue).toBeLessThanOrEqual(90); | |
| - }); | |
| - | |
| - it("should apply custom className", () => { | |
| - const customClass = "custom-loader-class"; | |
| - const { container } = render( | |
| - <DatabaseSyncLoader className={customClass} />, | |
| - ); | |
| - | |
| - expect(container.firstChild).toHaveClass(customClass); | |
| - }); | |
| - | |
| - it("should render database icon", () => { | |
| - const { container } = render(<DatabaseSyncLoader />); | |
| - | |
| - // Check for SVG icon by looking for SVG element | |
| - const svg = container.querySelector("svg"); | |
| - expect(svg).toBeInTheDocument(); | |
| - expect(screen.getByText("Transformity Database")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should render spinner elements", () => { | |
| - const { container } = render(<DatabaseSyncLoader />); | |
| - | |
| - // Check for spinner elements by class names | |
| - const spinners = container.querySelectorAll( | |
| - ".animate-spin, .animate-pulse", | |
| - ); | |
| - expect(spinners.length).toBeGreaterThan(0); | |
| - }); | |
| - | |
| - it("should cleanup timers on unmount", () => { | |
| - const { unmount } = render(<DatabaseSyncLoader showProgress={true} />); | |
| - | |
| - // Start the timers | |
| - act(() => { | |
| - vi.advanceTimersByTime(100); | |
| - }); | |
| - | |
| - // Unmount component | |
| - unmount(); | |
| - | |
| - // Advance timers after unmount - should not cause errors | |
| - act(() => { | |
| - vi.advanceTimersByTime(1000); | |
| - }); | |
| - | |
| - // No errors should be thrown | |
| - expect(true).toBe(true); | |
| - }); | |
| - | |
| - it("should handle empty message gracefully", () => { | |
| - render(<DatabaseSyncLoader message="" />); | |
| - | |
| - // Should still render other elements | |
| - expect( | |
| - screen.getByText("Please wait while we prepare your data"), | |
| - ).toBeInTheDocument(); | |
| - expect(screen.getByText("Transformity Database")).toBeInTheDocument(); | |
| - }); | |
| -}); | |
| diff --git a/src/components/__tests__/SalePageSyncOverlay.test.tsx b/src/components/__tests__/SalePageSyncOverlay.test.tsx | |
| deleted file mode 100644 | |
| index fe47e41e..00000000 | |
| --- a/src/components/__tests__/SalePageSyncOverlay.test.tsx | |
| +++ /dev/null | |
| @@ -1,207 +0,0 @@ | |
| -import { render, screen } from "@testing-library/react"; | |
| -import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| -import { SalePageSyncOverlay } from "../SalePageSyncOverlay"; | |
| - | |
| -// Mock the dependencies | |
| -vi.mock("../DatabaseSyncLoader", () => ({ | |
| - DatabaseSyncLoader: vi.fn(({ message, showProgress, className }) => ( | |
| - <div | |
| - data-testid="database-sync-loader" | |
| - data-message={message} | |
| - data-show-progress={showProgress} | |
| - className={className} | |
| - > | |
| - Mocked DatabaseSyncLoader | |
| - </div> | |
| - )), | |
| -})); | |
| - | |
| -vi.mock("../pg-lite/PGliteSyncContext", () => ({ | |
| - usePGliteSync: vi.fn(), | |
| -})); | |
| - | |
| -import { DatabaseSyncLoader } from "../DatabaseSyncLoader"; | |
| -import { usePGliteSync } from "../pg-lite/PGliteSyncContext"; | |
| - | |
| -const mockUsePGliteSync = usePGliteSync as any; | |
| -const MockDatabaseSyncLoader = DatabaseSyncLoader as any; | |
| - | |
| -describe("SalePageSyncOverlay", () => { | |
| - const defaultChildren = <div data-testid="child-content">Test Content</div>; | |
| - | |
| - beforeEach(() => { | |
| - vi.clearAllMocks(); | |
| - }); | |
| - | |
| - it("should render children when not syncing", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: false, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect(screen.getByTestId("child-content")).toBeInTheDocument(); | |
| - expect(screen.getByText("Test Content")).toBeInTheDocument(); | |
| - expect( | |
| - screen.queryByTestId("database-sync-loader"), | |
| - ).not.toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should render sync overlay when syncing", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: true, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect(screen.getByTestId("database-sync-loader")).toBeInTheDocument(); | |
| - expect(screen.queryByTestId("child-content")).not.toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should pass correct props to DatabaseSyncLoader when syncing", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: true, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect(MockDatabaseSyncLoader).toHaveBeenCalledWith( | |
| - expect.objectContaining({ | |
| - message: "Syncing POS database", | |
| - showProgress: true, | |
| - className: "shadow-lg", | |
| - }), | |
| - expect.any(Object), | |
| - ); | |
| - }); | |
| - | |
| - it("should render informational text when syncing", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: true, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect( | |
| - screen.getByText("We're preparing your point-of-sale system."), | |
| - ).toBeInTheDocument(); | |
| - expect( | |
| - screen.getByText("This usually takes just a few moments..."), | |
| - ).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should have correct overlay styling classes when syncing", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: true, | |
| - }); | |
| - | |
| - const { container } = render( | |
| - <SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>, | |
| - ); | |
| - | |
| - const overlay = container.firstChild as HTMLElement; | |
| - expect(overlay).toHaveClass( | |
| - "fixed", | |
| - "inset-0", | |
| - "z-50", | |
| - "flex", | |
| - "items-center", | |
| - "justify-center", | |
| - ); | |
| - expect(overlay).toHaveClass("bg-background/95", "backdrop-blur-sm"); | |
| - }); | |
| - | |
| - it("should handle multiple children when not syncing", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: false, | |
| - }); | |
| - | |
| - const multipleChildren = ( | |
| - <> | |
| - <div data-testid="child-1">Child 1</div> | |
| - <div data-testid="child-2">Child 2</div> | |
| - </> | |
| - ); | |
| - | |
| - render(<SalePageSyncOverlay>{multipleChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect(screen.getByTestId("child-1")).toBeInTheDocument(); | |
| - expect(screen.getByTestId("child-2")).toBeInTheDocument(); | |
| - expect( | |
| - screen.queryByTestId("database-sync-loader"), | |
| - ).not.toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should handle null children gracefully", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: false, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{null}</SalePageSyncOverlay>); | |
| - | |
| - expect( | |
| - screen.queryByTestId("database-sync-loader"), | |
| - ).not.toBeInTheDocument(); | |
| - // Should not throw any errors | |
| - }); | |
| - | |
| - it("should handle undefined children gracefully", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: false, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{undefined}</SalePageSyncOverlay>); | |
| - | |
| - expect( | |
| - screen.queryByTestId("database-sync-loader"), | |
| - ).not.toBeInTheDocument(); | |
| - // Should not throw any errors | |
| - }); | |
| - | |
| - it("should transition correctly from syncing to not syncing", () => { | |
| - const { rerender } = render( | |
| - <SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>, | |
| - ); | |
| - | |
| - // Initially syncing | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: true, | |
| - }); | |
| - rerender(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect(screen.getByTestId("database-sync-loader")).toBeInTheDocument(); | |
| - expect(screen.queryByTestId("child-content")).not.toBeInTheDocument(); | |
| - | |
| - // Stop syncing | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: false, | |
| - }); | |
| - rerender(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect( | |
| - screen.queryByTestId("database-sync-loader"), | |
| - ).not.toBeInTheDocument(); | |
| - expect(screen.getByTestId("child-content")).toBeInTheDocument(); | |
| - }); | |
| - | |
| - it("should call usePGliteSync hook", () => { | |
| - mockUsePGliteSync.mockReturnValue({ | |
| - isSyncing: false, | |
| - }); | |
| - | |
| - render(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - | |
| - expect(mockUsePGliteSync).toHaveBeenCalledTimes(1); | |
| - }); | |
| - | |
| - it("should handle sync context errors gracefully", () => { | |
| - // Mock the hook to throw an error | |
| - mockUsePGliteSync.mockImplementation(() => { | |
| - throw new Error("Context not found"); | |
| - }); | |
| - | |
| - expect(() => { | |
| - render(<SalePageSyncOverlay>{defaultChildren}</SalePageSyncOverlay>); | |
| - }).toThrow("Context not found"); | |
| - }); | |
| -}); | |
| diff --git a/src/components/common/CommandMenuShortcutOverlay.tsx b/src/components/common/CommandMenuShortcutOverlay.tsx | |
| new file mode 100644 | |
| index 00000000..ff7855b5 | |
| --- /dev/null | |
| +++ b/src/components/common/CommandMenuShortcutOverlay.tsx | |
| @@ -0,0 +1,56 @@ | |
| +import { useEffect, useState } from "react"; | |
| + | |
| +interface CommandMenuShortcutOverlayProps { | |
| + /** | |
| + * Whether to display a transparent overlay that intercepts clicks | |
| + * Useful for pages with iframes to ensure keyboard shortcuts work | |
| + */ | |
| + withOverlay?: boolean; | |
| +} | |
| + | |
| +export const CommandMenuShortcutOverlay = ({ | |
| + withOverlay = false, | |
| +}: CommandMenuShortcutOverlayProps) => { | |
| + const [showOverlay, setShowOverlay] = useState(false); | |
| + | |
| + useEffect(() => { | |
| + const handleKeyDown = (e: KeyboardEvent) => { | |
| + if (e.key === "k" && (e.metaKey || e.ctrlKey)) { | |
| + e.preventDefault(); | |
| + // Dispatch custom event that CommandMenu can listen to | |
| + window.dispatchEvent(new CustomEvent("commandMenuTrigger")); | |
| + } | |
| + }; | |
| + | |
| + const handleIframeLoaded = () => { | |
| + setShowOverlay(true); | |
| + }; | |
| + | |
| + document.addEventListener("keydown", handleKeyDown); | |
| + window.addEventListener("iframeLoaded", handleIframeLoaded); | |
| + | |
| + return () => { | |
| + document.removeEventListener("keydown", handleKeyDown); | |
| + window.removeEventListener("iframeLoaded", handleIframeLoaded); | |
| + }; | |
| + }, []); | |
| + | |
| + const handleOverlayClick = () => { | |
| + // Hide overlay temporarily when user clicks, then show it again | |
| + // This allows clicks to pass through to the iframe content | |
| + setShowOverlay(false); | |
| + setTimeout(() => setShowOverlay(true), 100); | |
| + }; | |
| + | |
| + if (!withOverlay || !showOverlay) return null; | |
| + | |
| + return ( | |
| + <div | |
| + onClick={handleOverlayClick} | |
| + className="absolute inset-0 bg-transparent z-[1000] pointer-events-auto" | |
| + tabIndex={0} | |
| + onFocus={(e) => e.currentTarget.blur()} | |
| + aria-hidden="true" | |
| + /> | |
| + ); | |
| +}; | |
| diff --git a/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx b/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx | |
| index 63cb4fc9..5771014c 100644 | |
| --- a/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx | |
| +++ b/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx | |
| @@ -1,4 +1,4 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| +import { Meta, StoryObj } from "@storybook/react/*"; | |
| import { expect, userEvent, waitFor, within } from "@storybook/test"; | |
| import { useState } from "react"; | |
| import { EmployeePinInput } from "./EmployeePinInput"; | |
| diff --git a/src/components/common/EraseDatabaseButton.tsx b/src/components/common/EraseDatabaseButton.tsx | |
| deleted file mode 100644 | |
| index 032d0527..00000000 | |
| --- a/src/components/common/EraseDatabaseButton.tsx | |
| +++ /dev/null | |
| @@ -1,121 +0,0 @@ | |
| -import { usePGlite } from "@electric-sql/pglite-react"; | |
| -import { ERASE_OPFS_DB } from "components/pg-lite/PgliteOptions"; | |
| -import { | |
| - AlertDialog, | |
| - AlertDialogAction, | |
| - AlertDialogCancel, | |
| - AlertDialogContent, | |
| - AlertDialogDescription, | |
| - AlertDialogFooter, | |
| - AlertDialogHeader, | |
| - AlertDialogTitle, | |
| - AlertDialogTrigger, | |
| -} from "components/ui/alert-dialog"; | |
| -import { Button } from "components/ui/button"; | |
| -import { useToast } from "components/ui/use-toast"; | |
| -import { useEntity } from "context/EntityProvider"; | |
| -import { Database, Loader2, Trash2 } from "lucide-react"; | |
| -import { useState } from "react"; | |
| - | |
| -interface EraseDatabaseButtonProps { | |
| - className?: string; | |
| -} | |
| - | |
| -export const EraseDatabaseButton: React.FC<EraseDatabaseButtonProps> = ({ | |
| - className, | |
| -}) => { | |
| - const [isErasing, setIsErasing] = useState(false); | |
| - const [isDialogOpen, setIsDialogOpen] = useState(false); | |
| - const { toast } = useToast(); | |
| - const db = usePGlite(); | |
| - const [entity] = useEntity(); | |
| - | |
| - const handleErase = async () => { | |
| - try { | |
| - setIsErasing(true); | |
| - | |
| - await ERASE_OPFS_DB(db, entity?.id ?? 0); | |
| - | |
| - toast({ | |
| - title: "Database Erased Successfully", | |
| - description: "All local data has been permanently deleted.", | |
| - }); | |
| - | |
| - setIsDialogOpen(false); | |
| - } catch (error) { | |
| - console.error("Failed to erase database:", error); | |
| - toast({ | |
| - title: "Erase Failed", | |
| - description: "Failed to erase the local database. Please try again.", | |
| - variant: "destructive", | |
| - }); | |
| - } finally { | |
| - setIsErasing(false); | |
| - } | |
| - }; | |
| - | |
| - return ( | |
| - <AlertDialog open={isDialogOpen} onOpenChange={setIsDialogOpen}> | |
| - <AlertDialogTrigger asChild> | |
| - <Button | |
| - variant="destructive" | |
| - className={`gap-2 ${className}`} | |
| - disabled={isErasing} | |
| - > | |
| - <Database className="h-4 w-4" /> | |
| - Erase Local Database | |
| - </Button> | |
| - </AlertDialogTrigger> | |
| - | |
| - <AlertDialogContent className="max-w-md"> | |
| - <AlertDialogHeader> | |
| - <AlertDialogTitle className="flex items-center gap-2 text-destructive"> | |
| - <Trash2 className="h-5 w-5" /> | |
| - Erase Local Database | |
| - </AlertDialogTitle> | |
| - <AlertDialogDescription className="text-left space-y-2"> | |
| - <p className="font-medium text-foreground"> | |
| - This action cannot be undone. | |
| - </p> | |
| - <p> | |
| - This will permanently delete all data stored in the Origin Private | |
| - File System (OPFS) database on this device and trigger a re-sync, | |
| - including: | |
| - </p> | |
| - <ul className="list-disc list-inside space-y-1 text-sm"> | |
| - <li>Transaction history</li> | |
| - <li>Product catalog cache</li> | |
| - <li>User preferences</li> | |
| - <li>Offline data</li> | |
| - </ul> | |
| - <p className="text-sm text-muted-foreground"> | |
| - You will need to sync data from the server after erasing, which | |
| - will take ~5 minutes. | |
| - </p> | |
| - </AlertDialogDescription> | |
| - </AlertDialogHeader> | |
| - | |
| - <AlertDialogFooter> | |
| - <AlertDialogCancel disabled={isErasing}>Cancel</AlertDialogCancel> | |
| - <AlertDialogAction | |
| - onClick={handleErase} | |
| - disabled={isErasing} | |
| - className="bg-destructive text-destructive-foreground hover:bg-destructive/90" | |
| - > | |
| - {isErasing ? ( | |
| - <> | |
| - <Loader2 className="h-4 w-4 animate-spin mr-2" /> | |
| - Erasing... | |
| - </> | |
| - ) : ( | |
| - <> | |
| - <Trash2 className="h-4 w-4 mr-2" /> | |
| - Erase Database | |
| - </> | |
| - )} | |
| - </AlertDialogAction> | |
| - </AlertDialogFooter> | |
| - </AlertDialogContent> | |
| - </AlertDialog> | |
| - ); | |
| -}; | |
| diff --git a/src/components/common/PurchaseOrderFinalizationDialog.tsx b/src/components/common/PurchaseOrderFinalizationDialog.tsx | |
| index 7d12de80..273a0ba6 100644 | |
| --- a/src/components/common/PurchaseOrderFinalizationDialog.tsx | |
| +++ b/src/components/common/PurchaseOrderFinalizationDialog.tsx | |
| @@ -66,7 +66,6 @@ export const PurchaseOrderFinalizationDialog: React.FC< | |
| if (open) { | |
| form.reset(defaultValues); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [open, form]); | |
| const onSubmit = async (data: FormData) => { | |
| diff --git a/src/components/common/SalesHistoryCard/SalesHistoryCard.tsx b/src/components/common/SalesHistoryCard/SalesHistoryCard.tsx | |
| index ad6c3537..6b165c73 100644 | |
| --- a/src/components/common/SalesHistoryCard/SalesHistoryCard.tsx | |
| +++ b/src/components/common/SalesHistoryCard/SalesHistoryCard.tsx | |
| @@ -532,7 +532,6 @@ const SaleHistoryVerticalTable = ({ | |
| captureException(error); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| aggregateChildren, | |
| endDate, | |
| diff --git a/src/components/common/SavingIndicator/SavingIndicator.stories.tsx b/src/components/common/SavingIndicator/SavingIndicator.stories.tsx | |
| index ee6d48c8..c72eaefc 100644 | |
| --- a/src/components/common/SavingIndicator/SavingIndicator.stories.tsx | |
| +++ b/src/components/common/SavingIndicator/SavingIndicator.stories.tsx | |
| @@ -1,4 +1,4 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| +import { Meta, StoryObj } from "@storybook/react/*"; | |
| import { SavingIndicator } from "./SavingIndicator"; | |
| const meta = { | |
| diff --git a/src/components/feature-flags/useFeatureFlagEnabled.tsx b/src/components/feature-flags/useFeatureFlagEnabled.tsx | |
| deleted file mode 100644 | |
| index 1d42e923..00000000 | |
| --- a/src/components/feature-flags/useFeatureFlagEnabled.tsx | |
| +++ /dev/null | |
| @@ -1,41 +0,0 @@ | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { usePostHog } from "posthog-js/react"; | |
| -import { useEffect, useState } from "react"; | |
| -import { BooleanParam, useQueryParam } from "use-query-params"; | |
| - | |
| -export function useFeatureFlagEnabled( | |
| - flag: string, | |
| - defaultValue: boolean = false, | |
| -): boolean { | |
| - const client = usePostHog(); | |
| - const [query] = useQueryParam(flag, BooleanParam); | |
| - | |
| - const [featureEnabled, setFeatureEnabled] = useState<boolean | undefined>( | |
| - () => { | |
| - try { | |
| - return client.isFeatureEnabled(flag); | |
| - } catch (error) { | |
| - captureException(error); | |
| - return defaultValue; | |
| - } | |
| - }, | |
| - ); | |
| - | |
| - useEffect(() => { | |
| - return client.onFeatureFlags(() => { | |
| - setFeatureEnabled((prev) => { | |
| - try { | |
| - client.isFeatureEnabled(flag); | |
| - return client.isFeatureEnabled(flag); | |
| - } catch (error) { | |
| - captureException(error); | |
| - return prev; // Return previous state if there's an error | |
| - } | |
| - }); | |
| - }); | |
| - }, [client, flag]); | |
| - | |
| - const val = query ?? featureEnabled ?? defaultValue; | |
| - console.log(`Feature flag "${flag}" is ${val ? "enabled" : "disabled"}.`); | |
| - return true; | |
| -} | |
| diff --git a/src/components/feature-flags/useOfflineModeDataSyncMigrationFlag.tsx b/src/components/feature-flags/useOfflineModeDataSyncMigrationFlag.tsx | |
| deleted file mode 100644 | |
| index beedd549..00000000 | |
| --- a/src/components/feature-flags/useOfflineModeDataSyncMigrationFlag.tsx | |
| +++ /dev/null | |
| @@ -1,4 +0,0 @@ | |
| -import { useFeatureFlagEnabled } from "./useFeatureFlagEnabled"; | |
| - | |
| -export const useOfflineModeDataSyncMigrationFlag = () => | |
| - useFeatureFlagEnabled("offline_mode_data_sync", false); | |
| diff --git a/src/components/fulfillment/FulfillmentConfirmationModal.tsx b/src/components/fulfillment/FulfillmentConfirmationModal.tsx | |
| deleted file mode 100644 | |
| index 4968bdb2..00000000 | |
| --- a/src/components/fulfillment/FulfillmentConfirmationModal.tsx | |
| +++ /dev/null | |
| @@ -1,226 +0,0 @@ | |
| -import { PermissionedButton } from "components/Auth/PermissionedButton"; | |
| -import { Badge } from "components/ui/badge"; | |
| -import { Button } from "components/ui/button"; | |
| -import { | |
| - Dialog, | |
| - DialogContent, | |
| - DialogDescription, | |
| - DialogFooter, | |
| - DialogHeader, | |
| - DialogTitle, | |
| -} from "components/ui/dialog"; | |
| -import { useToast } from "components/ui/use-toast"; | |
| -import { format } from "date-fns"; | |
| -import { | |
| - CalendarDays, | |
| - Clock, | |
| - Loader2, | |
| - MapPin, | |
| - Package, | |
| - Truck, | |
| -} from "lucide-react"; | |
| -import { | |
| - useGetFulfillment, | |
| - usePatchFulfillmentId, | |
| -} from "src/phoenix-generated"; | |
| - | |
| -interface FulfillmentConfirmationModalProps { | |
| - isOpen: boolean; | |
| - onClose: () => void; | |
| - fulfillmentId: string; | |
| - onSuccess?: () => void; | |
| -} | |
| - | |
| -const FulfillmentTypeIcon = { | |
| - PICKUP: MapPin, | |
| - SHIPPING: Truck, | |
| - DEFAULT: Package, | |
| -} as const; | |
| - | |
| -export const FulfillmentConfirmationModal: React.FC< | |
| - FulfillmentConfirmationModalProps | |
| -> = ({ isOpen, onClose, fulfillmentId, onSuccess }) => { | |
| - const { toast } = useToast(); | |
| - | |
| - const { data: fulfillment, isLoading: isFetchingFulfillment } = | |
| - useGetFulfillment(fulfillmentId, { | |
| - query: { | |
| - enabled: isOpen && !!fulfillmentId, | |
| - }, | |
| - }); | |
| - | |
| - const { mutateAsync: updateFulfillment, isPending: isUpdating } = | |
| - usePatchFulfillmentId({ | |
| - mutation: { | |
| - onSuccess: () => { | |
| - toast({ | |
| - title: "Success", | |
| - description: "Order has been fulfilled successfully", | |
| - variant: "success", | |
| - }); | |
| - onSuccess?.(); | |
| - onClose(); | |
| - }, | |
| - onError: (error: any) => { | |
| - toast({ | |
| - title: "Error", | |
| - description: | |
| - error?.response?.data?.message || "Failed to fulfill order", | |
| - variant: "destructive", | |
| - }); | |
| - }, | |
| - }, | |
| - }); | |
| - | |
| - const handleConfirmFulfillment = async () => { | |
| - await updateFulfillment({ | |
| - id: fulfillmentId, | |
| - data: { | |
| - status: "COMPLETED", | |
| - }, | |
| - }); | |
| - }; | |
| - | |
| - const TypeIcon = fulfillment?.type | |
| - ? FulfillmentTypeIcon[ | |
| - fulfillment.type as keyof typeof FulfillmentTypeIcon | |
| - ] || FulfillmentTypeIcon.DEFAULT | |
| - : FulfillmentTypeIcon.DEFAULT; | |
| - | |
| - return ( | |
| - <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}> | |
| - <DialogContent className="sm:max-w-[500px]"> | |
| - <DialogHeader> | |
| - <DialogTitle className="flex items-center gap-2"> | |
| - <TypeIcon className="w-5 h-5" /> | |
| - Confirm Fulfillment | |
| - </DialogTitle> | |
| - <DialogDescription> | |
| - Review the fulfillment details and confirm to complete the order. | |
| - </DialogDescription> | |
| - </DialogHeader> | |
| - | |
| - {isFetchingFulfillment ? ( | |
| - <div className="flex items-center justify-center py-8"> | |
| - <Loader2 className="w-8 h-8 animate-spin text-muted-foreground" /> | |
| - </div> | |
| - ) : fulfillment ? ( | |
| - <div className="space-y-4"> | |
| - <div className="flex items-center justify-between"> | |
| - <span className="text-sm font-medium text-muted-foreground"> | |
| - Status | |
| - </span> | |
| - <Badge | |
| - variant={ | |
| - fulfillment.status === "COMPLETED" | |
| - ? "successful" | |
| - : "secondary" | |
| - } | |
| - > | |
| - {fulfillment.status} | |
| - </Badge> | |
| - </div> | |
| - | |
| - <div className="flex items-center justify-between"> | |
| - <span className="text-sm font-medium text-muted-foreground"> | |
| - Type | |
| - </span> | |
| - <Badge variant="outline" className="uppercase"> | |
| - {fulfillment.type} | |
| - </Badge> | |
| - </div> | |
| - | |
| - {fulfillment.metadata?.pickup && ( | |
| - <div className="rounded-lg border p-3 space-y-2 bg-muted/30"> | |
| - <div className="flex items-center gap-2 text-sm font-medium"> | |
| - <MapPin className="w-4 h-4" /> | |
| - Pickup Details | |
| - </div> | |
| - <div className="text-sm text-muted-foreground pl-6"> | |
| - Location: {fulfillment.metadata.pickup.pickup_location} | |
| - </div> | |
| - </div> | |
| - )} | |
| - | |
| - {fulfillment.metadata?.shipping && ( | |
| - <div className="rounded-lg border p-3 space-y-2 bg-muted/30"> | |
| - <div className="flex items-center gap-2 text-sm font-medium"> | |
| - <Truck className="w-4 h-4" /> | |
| - Shipping Details | |
| - </div> | |
| - <div className="text-sm text-muted-foreground pl-6 space-y-1"> | |
| - <div>Carrier: {fulfillment.metadata.shipping.carrier}</div> | |
| - <div> | |
| - Tracking: {fulfillment.metadata.shipping.tracking_number} | |
| - </div> | |
| - </div> | |
| - </div> | |
| - )} | |
| - | |
| - <div className="grid grid-cols-2 gap-4 pt-2"> | |
| - <div className="flex items-center gap-2 text-sm text-muted-foreground"> | |
| - <CalendarDays className="w-4 h-4" /> | |
| - <div> | |
| - <div className="font-medium">Created</div> | |
| - <div> | |
| - {format( | |
| - new Date(fulfillment.createdAt), | |
| - "MMM d, yyyy h:mm a", | |
| - )} | |
| - </div> | |
| - </div> | |
| - </div> | |
| - <div className="flex items-center gap-2 text-sm text-muted-foreground"> | |
| - <Clock className="w-4 h-4" /> | |
| - <div> | |
| - <div className="font-medium">Updated</div> | |
| - <div> | |
| - {format( | |
| - new Date(fulfillment.updatedAt), | |
| - "MMM d, yyyy h:mm a", | |
| - )} | |
| - </div> | |
| - </div> | |
| - </div> | |
| - </div> | |
| - | |
| - {fulfillment.status === "COMPLETE" && ( | |
| - <div className="rounded-lg bg-green-50 border border-green-200 p-3 text-sm text-green-800"> | |
| - This order has already been fulfilled. | |
| - </div> | |
| - )} | |
| - </div> | |
| - ) : ( | |
| - <div className="py-8 text-center text-muted-foreground"> | |
| - Unable to load fulfillment details | |
| - </div> | |
| - )} | |
| - | |
| - <DialogFooter> | |
| - <Button variant="outline" onClick={onClose} disabled={isUpdating}> | |
| - Cancel | |
| - </Button> | |
| - <PermissionedButton | |
| - requires="fulfillment/*:update" | |
| - onClick={handleConfirmFulfillment} | |
| - disabled={ | |
| - isUpdating || | |
| - isFetchingFulfillment || | |
| - !fulfillment || | |
| - ["COMPLETED", "CANCELED"].includes(fulfillment?.status ?? "") | |
| - } | |
| - > | |
| - {isUpdating ? ( | |
| - <> | |
| - <Loader2 className="mr-2 h-4 w-4 animate-spin" /> | |
| - Confirming... | |
| - </> | |
| - ) : ( | |
| - "Confirm Fulfillment" | |
| - )} | |
| - </PermissionedButton> | |
| - </DialogFooter> | |
| - </DialogContent> | |
| - </Dialog> | |
| - ); | |
| -}; | |
| diff --git a/src/components/label/LabelPrinterContext.tsx b/src/components/label/LabelPrinterContext.tsx | |
| index 3140c9f1..b4ac7040 100644 | |
| --- a/src/components/label/LabelPrinterContext.tsx | |
| +++ b/src/components/label/LabelPrinterContext.tsx | |
| @@ -636,7 +636,6 @@ export const LabelPrintProvider = ({ children }: { children: ReactNode }) => { | |
| await writeData(textToPrint); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [SMALL_HEIGHT_LABEL, writeData], | |
| ); | |
| diff --git a/src/components/loyalty/CustomerProfile/CustomerLoyaltyPointsTable.tsx b/src/components/loyalty/CustomerProfile/CustomerLoyaltyPointsTable.tsx | |
| index b4ba2b91..7463217b 100644 | |
| --- a/src/components/loyalty/CustomerProfile/CustomerLoyaltyPointsTable.tsx | |
| +++ b/src/components/loyalty/CustomerProfile/CustomerLoyaltyPointsTable.tsx | |
| @@ -77,7 +77,6 @@ const CustomerLoyaltyPointsTable: React.FC<CustomerTransactionsTableProps> = ({ | |
| useEffect(() => { | |
| onQueryKey(queryKeyRef); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [queryKey]); | |
| return ( | |
| diff --git a/src/components/loyalty/CustomerProfile/CustomerTransactionsTable.tsx b/src/components/loyalty/CustomerProfile/CustomerTransactionsTable.tsx | |
| index af9e5652..871a3dcc 100644 | |
| --- a/src/components/loyalty/CustomerProfile/CustomerTransactionsTable.tsx | |
| +++ b/src/components/loyalty/CustomerProfile/CustomerTransactionsTable.tsx | |
| @@ -49,7 +49,6 @@ export const CustomerTransactionsTable: React.FC< | |
| useEffect(() => { | |
| onQueryKey(queryKeyRef); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [queryKey]); | |
| return ( | |
| diff --git a/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountDetailsView.tsx b/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountDetailsView.tsx | |
| index 35968482..dfb4f517 100644 | |
| --- a/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountDetailsView.tsx | |
| +++ b/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountDetailsView.tsx | |
| @@ -370,13 +370,6 @@ export const PayHouseAmountFormWrapper: React.FC< | |
| salesChannel={inStoreSalesChannel} | |
| reviewTransactionModal={reviewTransactionModal} | |
| payAfterConfirm={false} | |
| - // Payment method functions (fallback implementations for house account context) | |
| - paymentMethodTypeToPaymentMethod={{}} | |
| - calculateMethodsWithPrices={() => []} | |
| - findBestPaymentMethod={() => null} | |
| - isCalculatingBackgroundPaymentMethodTotals={false} | |
| - selectedSalesChannel={undefined} | |
| - setSkipSetItemsInCart={() => undefined} | |
| > | |
| <PayHouseAmountForm | |
| houseAccountId={houseAccountId} | |
| diff --git a/src/components/navbar/NavBarPlain.tsx b/src/components/navbar/NavBarPlain.tsx | |
| index 4c981880..97b6332c 100644 | |
| --- a/src/components/navbar/NavBarPlain.tsx | |
| +++ b/src/components/navbar/NavBarPlain.tsx | |
| @@ -5,7 +5,6 @@ import { Separator } from "components/ui/separator"; | |
| import { useEntity } from "context/EntityProvider"; | |
| import { Menu } from "lucide-react"; | |
| import React, { useState } from "react"; | |
| -import { useMediaQuery } from "usehooks-ts"; | |
| import { LockButton } from "../Auth/LockButton"; | |
| import { Breadcrumbs } from "../common/Breadcrumbs/Breadcrumbs"; | |
| import { ItemSearchShortcut } from "../common/ItemSearchShortcut"; | |
| @@ -45,8 +44,6 @@ export const NavBarPlain: React.FC<NavBarProps> = ({ | |
| const onOpen = () => setIsOpen(true); | |
| const onClose = () => setIsOpen(false); | |
| - const isMobile = useMediaQuery("(max-width: 768px)"); | |
| - | |
| return ( | |
| <> | |
| <div | |
| @@ -57,25 +54,23 @@ export const NavBarPlain: React.FC<NavBarProps> = ({ | |
| )} | |
| > | |
| {/* Mobile */} | |
| - {isMobile && ( | |
| - <div className="flex w-full items-center justify-between space-x-2"> | |
| - <div className="flex space-x-2"> | |
| - <Button | |
| - variant="outline" | |
| - size="sm" | |
| - onClick={onOpen} | |
| - className="p-2 md:p-3" | |
| - aria-label="Open menu" | |
| - > | |
| - <Menu className="h-4 w-4" /> | |
| - </Button> | |
| - {!!title && <h2 className="text-lg font-semibold">{title}</h2>} | |
| - </div> | |
| - <div> | |
| - <CommandMenu showPlaceholder={false} /> | |
| - </div> | |
| + <div className="flex md:hidden w-full md:w-fit items-center justify-between space-x-2 md:space-x-3"> | |
| + <div className="flex space-x-2"> | |
| + <Button | |
| + variant="outline" | |
| + size="sm" | |
| + onClick={onOpen} | |
| + className="p-2 md:p-3" | |
| + aria-label="Open menu" | |
| + > | |
| + <Menu className="h-4 w-4" /> | |
| + </Button> | |
| + {!!title && <h2 className="text-lg font-semibold">{title}</h2>} | |
| </div> | |
| - )} | |
| + <div> | |
| + <CommandMenu showPlaceholder={false} /> | |
| + </div> | |
| + </div> | |
| <div className="hidden md:flex items-center space-x-2 md:space-x-3"> | |
| {!hideMenu && <MenuLinks />} | |
| @@ -108,16 +103,14 @@ export const NavBarPlain: React.FC<NavBarProps> = ({ | |
| {/* Mobile Drawer */} | |
| <MobileNavDrawer isOpen={isOpen} onClose={onClose} title={title}> | |
| - {isOpen && ( | |
| - <MobileNavContent | |
| - title={title} | |
| - hideMenu={hideMenu} | |
| - hideOverride={hideOverride} | |
| - hidePopRegister={hidePopRegister} | |
| - hideSearchShortcut={hideSearchShortcut} | |
| - hideSalesScreenShortcut={hideSalesScreenShortcut} | |
| - /> | |
| - )} | |
| + <MobileNavContent | |
| + title={title} | |
| + hideMenu={hideMenu} | |
| + hideOverride={hideOverride} | |
| + hidePopRegister={hidePopRegister} | |
| + hideSearchShortcut={hideSearchShortcut} | |
| + hideSalesScreenShortcut={hideSalesScreenShortcut} | |
| + /> | |
| </MobileNavDrawer> | |
| </> | |
| ); | |
| diff --git a/src/components/navbar/SaleScreenNavBar.tsx b/src/components/navbar/SaleScreenNavBar.tsx | |
| index e2b30693..b66d43dc 100644 | |
| --- a/src/components/navbar/SaleScreenNavBar.tsx | |
| +++ b/src/components/navbar/SaleScreenNavBar.tsx | |
| @@ -19,7 +19,7 @@ import { StoreInfoWithSelect } from "./StoreInfoWithSelect"; | |
| import EnvironmentTag from "./environment/EnvironmentTag"; | |
| export type SaleScreenNavBarProps = { | |
| - onSearchSelected?: (item?: EntityItemDetail) => void | Promise<void>; | |
| + onSearchSelected?: (item?: EntityItemDetail) => void; | |
| }; | |
| const SaleScreenNavBar = forwardRef<ComboboxSelectRef, SaleScreenNavBarProps>( | |
| diff --git a/src/components/paymentProcessor/FinixPaymentModal.tsx b/src/components/paymentProcessor/FinixPaymentModal.tsx | |
| index 15d07def..88aee6c5 100644 | |
| --- a/src/components/paymentProcessor/FinixPaymentModal.tsx | |
| +++ b/src/components/paymentProcessor/FinixPaymentModal.tsx | |
| @@ -1,4 +1,3 @@ | |
| -import { CreditCardPriceOption } from "components/SalesScreenComponents/Modals/ManualCardPunchModal"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| import { TransactionPaymentForm } from "generated/types"; | |
| import { useEffect } from "react"; | |
| @@ -7,14 +6,11 @@ const finixEnv = import.meta.env.VITE_APP_FINIX_ENV; | |
| export type FinixPaymentModalProps = { | |
| onFormSubmit: () => void; | |
| - priceSelected: CreditCardPriceOption; | |
| }; | |
| -export const FinixPaymentModal = ({ | |
| - onFormSubmit, | |
| - priceSelected, | |
| -}: FinixPaymentModalProps) => { | |
| - const { setAmountPaid, isPersisting } = useSalesPaymentContext(); | |
| +export const FinixPaymentModal = ({ onFormSubmit }: FinixPaymentModalProps) => { | |
| + const { transactionTotalPrice, setAmountPaid, isPersisting } = | |
| + useSalesPaymentContext(); | |
| const options = { | |
| showAddress: true, // show address fields in the form (default is false) | |
| @@ -53,8 +49,7 @@ export const FinixPaymentModal = ({ | |
| setAmountPaid({ | |
| amountPaid: 0, | |
| - creditCardAmountReceived: priceSelected.total, | |
| - paymentMethodId: priceSelected.method.id, | |
| + creditCardAmountReceived: transactionTotalPrice(), | |
| paymentForm: TransactionPaymentForm["CREDIT CARD"], | |
| creditCardId: token, | |
| }); | |
| @@ -68,7 +63,6 @@ export const FinixPaymentModal = ({ | |
| showAddress: true, | |
| onSubmit, | |
| }); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, []); | |
| return <div id="form" />; | |
| diff --git a/src/components/paymentProcessor/StripeCardPunchIn.tsx b/src/components/paymentProcessor/StripeCardPunchIn.tsx | |
| index 089a918b..bbe43d86 100644 | |
| --- a/src/components/paymentProcessor/StripeCardPunchIn.tsx | |
| +++ b/src/components/paymentProcessor/StripeCardPunchIn.tsx | |
| @@ -5,23 +5,22 @@ import { | |
| useStripe, | |
| } from "@stripe/react-stripe-js"; | |
| import { Button } from "@tremor/react"; | |
| -import { CreditCardPriceOption } from "components/SalesScreenComponents/Modals/ManualCardPunchModal"; | |
| import { useSalesPaymentContext } from "context/Sales/SalesPaymentContext"; | |
| import { TransactionPaymentForm } from "generated/types"; | |
| import { useState } from "react"; | |
| export type CheckoutFormProps = { | |
| onSubmit: () => void; | |
| - priceSelected: CreditCardPriceOption; | |
| }; | |
| -const CheckoutForm = ({ onSubmit, priceSelected }: CheckoutFormProps) => { | |
| +const CheckoutForm = ({ onSubmit }: CheckoutFormProps) => { | |
| const stripe = useStripe(); | |
| const elements = useElements(); | |
| const [errorMessage, setErrorMessage] = useState(); | |
| const [loading, setLoading] = useState(false); | |
| - const { setAmountPaid, isPersisting } = useSalesPaymentContext(); | |
| + const { transactionTotalPrice, setAmountPaid, isPersisting } = | |
| + useSalesPaymentContext(); | |
| const handleError = (error: any) => { | |
| setLoading(false); | |
| @@ -64,8 +63,7 @@ const CheckoutForm = ({ onSubmit, priceSelected }: CheckoutFormProps) => { | |
| setAmountPaid({ | |
| amountPaid: 0, | |
| - creditCardAmountReceived: priceSelected.total, | |
| - paymentMethodId: priceSelected.method.id, | |
| + creditCardAmountReceived: transactionTotalPrice(), | |
| paymentForm: TransactionPaymentForm["CREDIT CARD"], | |
| creditCardId: paymentMethod?.id, | |
| }); | |
| diff --git a/src/components/paymentProcessor/worldpay/WorldpayManualPaymentModal.tsx b/src/components/paymentProcessor/worldpay/WorldpayManualPaymentModal.tsx | |
| index dfc14313..33e4eda9 100644 | |
| --- a/src/components/paymentProcessor/worldpay/WorldpayManualPaymentModal.tsx | |
| +++ b/src/components/paymentProcessor/worldpay/WorldpayManualPaymentModal.tsx | |
| @@ -1,4 +1,3 @@ | |
| -import { CreditCardPriceOption } from "components/SalesScreenComponents/Modals/ManualCardPunchModal"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| import { | |
| AmountReceived, | |
| @@ -9,7 +8,6 @@ import { useScript } from "usehooks-ts"; | |
| export type WorldpayPaymentModalProps = { | |
| onFormSubmit: () => void; | |
| - priceSelected: CreditCardPriceOption; | |
| }; | |
| interface CustomWindow extends Window { | |
| @@ -23,9 +21,8 @@ declare let window: CustomWindow; | |
| const WorldpayManualPaymentModal = ({ | |
| onFormSubmit, | |
| - priceSelected, | |
| }: WorldpayPaymentModalProps) => { | |
| - const { setAmountPaid } = useSalesPaymentContext(); | |
| + const { transactionTotalPrice, setAmountPaid } = useSalesPaymentContext(); | |
| const [entity] = useEntitySelected(); | |
| const scriptLoading = useScript( | |
| @@ -60,10 +57,9 @@ const WorldpayManualPaymentModal = ({ | |
| console.log(response); | |
| window.setPaymentSuccessRef({ | |
| amountPaid: 0, | |
| - creditCardAmountReceived: ${priceSelected.total}, | |
| + creditCardAmountReceived: ${transactionTotalPrice()}, | |
| paymentForm: "CREDIT CARD", | |
| creditCardId: response.response.data.at(0).token, | |
| - paymentMethodId: ${priceSelected.method.id}, | |
| }); | |
| } | |
| PayFrame.onFinish = function (response) { | |
| @@ -81,8 +77,7 @@ const WorldpayManualPaymentModal = ({ | |
| return () => { | |
| document.body.removeChild(script); | |
| }; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| - }, [entity.creditCardMerchantOnlineId, scriptLoading, priceSelected.total]); // Empty dependency array ensures this runs only once on mount | |
| + }, [entity.creditCardMerchantOnlineId, scriptLoading, transactionTotalPrice]); // Empty dependency array ensures this runs only once on mount | |
| // Attach the setState function to the window | |
| useEffect(() => { | |
| diff --git a/src/components/payout/PayoutModal.tsx b/src/components/payout/PayoutModal.tsx | |
| index 35185176..e8dffe1d 100644 | |
| --- a/src/components/payout/PayoutModal.tsx | |
| +++ b/src/components/payout/PayoutModal.tsx | |
| @@ -208,7 +208,6 @@ const PayoutModal = ({ | |
| onClose(); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [postPayout, reset, onClose], | |
| ); | |
| diff --git a/src/components/pg-lite/PGliteProvider.tsx b/src/components/pg-lite/PGliteProvider.tsx | |
| deleted file mode 100644 | |
| index 99361495..00000000 | |
| --- a/src/components/pg-lite/PGliteProvider.tsx | |
| +++ /dev/null | |
| @@ -1,537 +0,0 @@ | |
| -import { PGliteProvider as _PGliteProvider } from "@electric-sql/pglite-react"; | |
| -import type { | |
| - MapColumnsFn, | |
| - ShapeToTableOptions, | |
| - SyncShapesToTablesResult, | |
| -} from "@electric-sql/pglite-sync"; | |
| -import { PGliteWorker } from "@electric-sql/pglite/worker"; | |
| -import Loading from "components/Loading"; | |
| -import PGWorker from "components/pg-lite/pglite-worker.ts?worker"; | |
| -import { firebaseAuth } from "config/Firebase/firebase"; | |
| -import { useEntity } from "context/EntityProvider"; | |
| -import { useEffect, useRef, useState } from "react"; | |
| -import { typeidUnboxed } from "typeid-js"; | |
| -import { useLocalStorage } from "usehooks-ts"; | |
| -import { | |
| - type CustomPGlite, | |
| - ERASE_OPFS_DB, | |
| - PG_LITE_INITIAL_SYNC_COMPLETE, | |
| - PGLITE_OPTIONS, | |
| -} from "./PgliteOptions"; | |
| - | |
| -/** | |
| - * Configuration for each table to be synced | |
| - * name: The name of the table in the local PGlite database | |
| - * primaryKey: The primary key columns for the table. This should match the primary key in the database as part of our abstraction. | |
| - * Electric requires the primary key to match our shape data. Example: If the primary key is id in the DB and our prefix is ei, then the primary key is id. Our abstraction will make it ei_id. | |
| - * columnPrefix: A prefix to add to each column name to avoid collisions | |
| - * columns: Optional additional columns to include in the sync. These should match the column names in the database. | |
| - * (on top of the columns returned by the shape) | |
| - * e.g. for foreign keys or metadata | |
| - */ | |
| -type TableConfig = { | |
| - name: string; | |
| - primaryKey: string[]; | |
| - columnPrefix: string; | |
| - columns: string[]; // Optional additional columns to include | |
| -}; | |
| - | |
| -const PGliteProvider = ({ children }: { children: React.ReactNode }) => { | |
| - const [client, setClient] = useState<CustomPGlite | undefined>(undefined); | |
| - | |
| - const subscriptionRef = useRef<SyncShapesToTablesResult>(); | |
| - const [entity] = useEntity(); | |
| - | |
| - const [, setInitialSyncComplete] = useLocalStorage( | |
| - PG_LITE_INITIAL_SYNC_COMPLETE(entity?.id ?? 0), | |
| - false, | |
| - ); | |
| - | |
| - useEffect(() => { | |
| - const currentUser = firebaseAuth.currentUser; | |
| - const getIdToken = currentUser?.getIdToken; | |
| - if (!getIdToken) { | |
| - console.error("No user is currently authenticated."); | |
| - return; | |
| - } | |
| - let worker: CustomPGlite | undefined; | |
| - void PGliteWorker.create( | |
| - new PGWorker({ | |
| - name: "pglite-worker", | |
| - }), | |
| - PGLITE_OPTIONS, | |
| - ).then(async (pg) => { | |
| - worker = pg; | |
| - | |
| - const tableConfigs: TableConfig[] = [ | |
| - { | |
| - name: "transaction_item_cost_type", | |
| - primaryKey: ["type"], | |
| - columnPrefix: "tict", | |
| - columns: ["type"], | |
| - }, | |
| - { | |
| - name: "cohort", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "co", | |
| - columns: ["id", "name", "created_at", "updated_at", "migration_id"], | |
| - }, | |
| - { | |
| - name: "cohort_item_size_unit", | |
| - primaryKey: ["size_unit"], | |
| - columnPrefix: "cits", | |
| - columns: ["size_unit"], | |
| - }, | |
| - { | |
| - name: "department_group", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "dg", | |
| - columns: [ | |
| - "id", | |
| - "cohort_id", | |
| - "name", | |
| - "created_at", | |
| - "updated_at", | |
| - "migration_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "department", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "dp", | |
| - columns: [ | |
| - "name", | |
| - "tax", | |
| - "bottledeposit", | |
| - "environmentfee", | |
| - "updated_at", | |
| - "id", | |
| - "cohort_id", | |
| - "has_revenue", | |
| - "department_group_id", | |
| - "migration_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "item_type", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "it", | |
| - columns: ["id", "type"], | |
| - }, | |
| - { | |
| - name: "cohort_item", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "ci", | |
| - columns: [ | |
| - "id", | |
| - "cohort_id", | |
| - "name", | |
| - "case_quantity", | |
| - "size", | |
| - "size_unit", | |
| - "alcohol_by_volume", | |
| - "deposit_multiplier", | |
| - "environment_fee_multiplier", | |
| - "parent_cohort_item_id", | |
| - "parent_quantity", | |
| - "notes", | |
| - "changed_by", | |
| - "created_at", | |
| - "updated_at", | |
| - "migration_id", | |
| - "parent_migration_id", | |
| - "department", | |
| - "brand", | |
| - "pack_size", | |
| - "alcoholic", | |
| - "vintage", | |
| - "item_type_id", | |
| - "version", | |
| - ], | |
| - }, | |
| - { | |
| - name: "cohort_vendor", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "cv", | |
| - columns: [ | |
| - "id", | |
| - "cohort_id", | |
| - "vendor_id", | |
| - "vendor_name", | |
| - "created_at", | |
| - "updated_at", | |
| - "changed_by", | |
| - "email", | |
| - "phone_number", | |
| - "migration_id", | |
| - "is_exclusive", | |
| - ], | |
| - }, | |
| - { | |
| - name: "entity_minimum_price_source_type", | |
| - primaryKey: ["type"], | |
| - columnPrefix: "empst", | |
| - columns: ["type"], | |
| - }, | |
| - { | |
| - name: "cohort_item_vintage", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "civ", | |
| - columns: [ | |
| - "id", | |
| - "cohort_item_id", | |
| - "vintage", | |
| - "rating", | |
| - "reviewer", | |
| - "note", | |
| - "created_at", | |
| - "updated_at", | |
| - "version", | |
| - "reviewer_code", | |
| - "cohort_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "address", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "adr", | |
| - columns: [ | |
| - "id", | |
| - "line1", | |
| - "line2", | |
| - "city", | |
| - "state", | |
| - "country", | |
| - "postal_code", | |
| - "created_at", | |
| - "updated_at", | |
| - ], | |
| - }, | |
| - { | |
| - name: "entity", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "ey", | |
| - columns: [ | |
| - "name", | |
| - "id", | |
| - "credit_card_merchant_application_id", | |
| - "credit_card_merchant_id", | |
| - "address", | |
| - "fintech_host", | |
| - "fintech_user", | |
| - "fintech_passwd", | |
| - "fintech_path", | |
| - "payment_processor", | |
| - "payment_fee_fixed", | |
| - "payment_fee_percent", | |
| - "updated_at", | |
| - "phone_number", | |
| - "cohort_id", | |
| - "location_id", | |
| - "timezone", | |
| - "created_at", | |
| - "card_not_present_payment_fee_fixed", | |
| - "card_not_present_payment_fee_percent", | |
| - "surcharge_fee", | |
| - "credit_card_merchant_token", | |
| - "credit_card_terminal_id", | |
| - "credit_card_merchant_online_id", | |
| - "short_name", | |
| - "transaction_item_cost_type", | |
| - "email", | |
| - "address_id", | |
| - "minimum_price_source_type", | |
| - ], | |
| - }, | |
| - { | |
| - name: "entity_item", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "ei", | |
| - columns: [ | |
| - "id", | |
| - "entity_id", | |
| - "cohort_item_id", | |
| - "price", | |
| - "minimum_price", | |
| - "cost", | |
| - "discount_allowed", | |
| - "quantity", | |
| - "aisle_location", | |
| - "fridge_location", | |
| - "last_quantity_received", | |
| - "changed_by", | |
| - "created_at", | |
| - "updated_at", | |
| - "migration_id", | |
| - "last_order_date", | |
| - "exclusive", | |
| - "case_cost", | |
| - "variable_cost_percent", | |
| - "last_cohort_vendor_id", | |
| - "preferred_cohort_vendor_id", | |
| - "average_cost", | |
| - "sellable", | |
| - "version", | |
| - "cohort_item_vintage_id", | |
| - "true_cost", | |
| - ], | |
| - }, | |
| - { | |
| - name: "entity_tag", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "et", | |
| - columns: ["id", "name", "updated_at", "cohort_id", "migration_id"], | |
| - }, | |
| - { | |
| - name: "entity_attribute", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "eattr", | |
| - columns: ["id", "description"], | |
| - }, | |
| - { | |
| - name: "entity_configuration", | |
| - primaryKey: ["entity_id", "attribute_id"], | |
| - columnPrefix: "ecfg", | |
| - columns: ["entity_id", "attribute_id", "value"], | |
| - }, | |
| - { | |
| - name: "register", | |
| - primaryKey: ["entity_id", "register_number"], | |
| - columnPrefix: "reg", | |
| - columns: [ | |
| - "entity_id", | |
| - "register_number", | |
| - "credit_card_device_id", | |
| - "updated_at", | |
| - ], | |
| - }, | |
| - { | |
| - name: "bill_denomination", | |
| - primaryKey: ["denomination_dollar_value"], | |
| - columnPrefix: "bd", | |
| - columns: ["denomination_dollar_value", "denomination_type"], | |
| - }, | |
| - { | |
| - name: "sales_channel_type", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "sct", | |
| - columns: ["id", "name", "description", "created_at", "config"], | |
| - }, | |
| - { | |
| - name: "cohort_price_level", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "cpl", | |
| - columns: [ | |
| - "id", | |
| - "cohort_id", | |
| - "name", | |
| - "markup_percent", | |
| - "markup_cohort_price_level_id", | |
| - "migration_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "entity_sales_channel", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "esc", | |
| - columns: [ | |
| - "id", | |
| - "sales_channel_type_id", | |
| - "entity_id", | |
| - "created_at", | |
| - "updated_at", | |
| - "account_id", | |
| - "active", | |
| - "external_location_id", | |
| - "name", | |
| - "taxable", | |
| - "price_level_id", | |
| - "external_integration_enabled", | |
| - "external_integration_attempt", | |
| - "external_address_line_1", | |
| - "external_address_line_2", | |
| - "external_address_city", | |
| - "external_address_state", | |
| - "external_address_zip", | |
| - "external_requestor_name", | |
| - "external_requestor_email", | |
| - "external_merchant_decision_maker_email", | |
| - "sftp_credentials", | |
| - "configuration", | |
| - "auto_add_new_departments", | |
| - "allow_negative_inventory", | |
| - ], | |
| - }, | |
| - { | |
| - name: "cohort_item_tag", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "cit", | |
| - columns: [ | |
| - "id", | |
| - "cohort_item_id", | |
| - "tag_id", | |
| - "updated_at", | |
| - "created_at", | |
| - "changed_by", | |
| - "cohort_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "cohort_item_barcode", | |
| - primaryKey: ["cohort_item_id", "barcode"], | |
| - columnPrefix: "cib", | |
| - columns: ["cohort_item_id", "barcode", "created_at", "cohort_id"], | |
| - }, | |
| - { | |
| - name: "cohort_item_vendor_item", | |
| - primaryKey: ["cohort_item_id", "cohort_vendor_id"], | |
| - columnPrefix: "civi", | |
| - columns: [ | |
| - "cohort_item_id", | |
| - "vendor", | |
| - "sku", | |
| - "updated_at", | |
| - "created_at", | |
| - "changed_by", | |
| - "cohort_vendor_id", | |
| - "cohort_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "entity_sales_channel_item", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "esci", | |
| - columns: [ | |
| - "id", | |
| - "entity_sales_channel_id", | |
| - "entity_item_id", | |
| - "active", | |
| - "created_at", | |
| - "updated_at", | |
| - "external_item_id", | |
| - "entity_id", | |
| - ], | |
| - }, | |
| - { | |
| - name: "casbin_rule_role", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "crr", | |
| - columns: ["id", "ptype", "v0", "v1", "v2", "v3", "v4", "v5"], | |
| - }, | |
| - { | |
| - name: "casbin_rule_user", | |
| - primaryKey: ["id"], | |
| - columnPrefix: "cru", | |
| - columns: ["id", "ptype", "v0", "v1", "v2", "v3", "v4", "v5"], | |
| - }, | |
| - // { name: "drawer_settlement", primaryKey: ["id"] }, | |
| - // { name: "transactionclosings", primaryKey: ["id"] }, | |
| - // Add more table configurations here as needed | |
| - ]; | |
| - | |
| - const shapes: Record<string, ShapeToTableOptions> = {}; | |
| - | |
| - const electricUrl = import.meta.env.VITE_APP_ZEUS_URL; | |
| - | |
| - tableConfigs.forEach((config) => { | |
| - const defaultMapColumnsPrefixed = ( | |
| - message: Parameters<MapColumnsFn>[0], | |
| - prefix?: string, | |
| - ) => { | |
| - if (prefix) { | |
| - return Object.fromEntries( | |
| - Object.entries(message.value).map(([key, value]) => [ | |
| - `${prefix}_${key}`, | |
| - value, | |
| - ]), | |
| - ); | |
| - } | |
| - return { ...message.value }; | |
| - }; | |
| - | |
| - const defaultMapColumns: MapColumnsFn = (message) => { | |
| - return defaultMapColumnsPrefixed(message, config.columnPrefix); | |
| - }; | |
| - | |
| - shapes[config.name] = { | |
| - shape: { | |
| - url: `${electricUrl}/v1/shape`, | |
| - headers: { | |
| - // Token will be refreshed on each request | |
| - Authorization: async () => | |
| - `Bearer ${await firebaseAuth.currentUser?.getIdToken()}`, | |
| - "X-Request-Id": () => typeidUnboxed<"req">("req"), | |
| - }, | |
| - params: { | |
| - table: config.name, | |
| - replica: "full", | |
| - columns: config.columns, | |
| - entityId: entity?.id.toString(), | |
| - }, | |
| - }, | |
| - table: config.name, | |
| - mapColumns: defaultMapColumns, | |
| - // Electric requires the primary key to match our shape data. Example: If the primary key is id in the DB and our prefix is ei, then the primary key is id. Our abstraction will make it ei_id. | |
| - primaryKey: config.primaryKey.map((col) => { | |
| - if (config.columnPrefix) { | |
| - return `${config.columnPrefix}_${col}`; | |
| - } | |
| - return col; | |
| - }), | |
| - onMustRefetch: async (tx) => { | |
| - console.log(`Refetching shape for table: ${config.name}`); | |
| - try { | |
| - await tx.exec(` | |
| - SET session_replication_role = 'replica'; | |
| - `); | |
| - await tx.exec(`TRUNCATE TABLE "${config.name}" CASCADE;`); | |
| - } catch (error) { | |
| - console.error(`Error clearing table ${config.name}:`, error); | |
| - await ERASE_OPFS_DB(pg, entity?.id ?? 0); | |
| - } | |
| - }, | |
| - }; | |
| - }); | |
| - | |
| - const sub = await pg.electric.syncShapesToTables({ | |
| - shapes: shapes, | |
| - key: `non-null`, // https://pglite.dev/docs/sync#syncshapestotables-api | |
| - initialInsertMethod: "csv", | |
| - onInitialSync: async () => { | |
| - console.log("Initial sync complete"); | |
| - setInitialSyncComplete(true); | |
| - await pg.exec(`SET session_replication_role = 'origin';`); | |
| - }, | |
| - }); | |
| - | |
| - subscriptionRef.current = sub; | |
| - | |
| - setClient(pg); | |
| - }); | |
| - | |
| - return () => { | |
| - console.log("Cleaning up PGlite worker"); | |
| - if (subscriptionRef.current) { | |
| - console.log("Unsubscribing from PGlite sync"); | |
| - subscriptionRef.current.unsubscribe(); | |
| - } | |
| - if (worker) { | |
| - void worker.close().then(() => { | |
| - console.log("PGlite worker closed"); | |
| - }); | |
| - } | |
| - }; | |
| - }, [entity?.id, setInitialSyncComplete]); | |
| - | |
| - if (!client) { | |
| - return <Loading />; | |
| - } | |
| - | |
| - return <_PGliteProvider db={client}>{children}</_PGliteProvider>; | |
| -}; | |
| - | |
| -const PGlineRolloutProvider = ({ children }: { children: React.ReactNode }) => { | |
| - return <PGliteProvider>{children}</PGliteProvider>; | |
| -}; | |
| - | |
| -export default PGlineRolloutProvider; | |
| diff --git a/src/components/pg-lite/PGliteSyncContext.tsx b/src/components/pg-lite/PGliteSyncContext.tsx | |
| deleted file mode 100644 | |
| index cd84fe63..00000000 | |
| --- a/src/components/pg-lite/PGliteSyncContext.tsx | |
| +++ /dev/null | |
| @@ -1,17 +0,0 @@ | |
| -import { useEntity } from "context/EntityProvider"; | |
| -import { useLocalStorage } from "usehooks-ts"; | |
| -import { PG_LITE_INITIAL_SYNC_COMPLETE } from "./PgliteOptions"; | |
| - | |
| -export const usePGliteSync = () => { | |
| - const [entity] = useEntity(); | |
| - const [initialSyncComplete] = useLocalStorage( | |
| - PG_LITE_INITIAL_SYNC_COMPLETE(entity?.id ?? 0), | |
| - false, | |
| - ); | |
| - | |
| - console.log("initialSyncComplete =", initialSyncComplete); | |
| - | |
| - return { | |
| - isSyncing: !initialSyncComplete, | |
| - }; | |
| -}; | |
| diff --git a/src/components/pg-lite/PgliteOptions.ts b/src/components/pg-lite/PgliteOptions.ts | |
| deleted file mode 100644 | |
| index c99cc879..00000000 | |
| --- a/src/components/pg-lite/PgliteOptions.ts | |
| +++ /dev/null | |
| @@ -1,59 +0,0 @@ | |
| -import { | |
| - type DebugLevel, | |
| - IdbFs, | |
| - type PGliteInterface, | |
| - type PGliteInterfaceExtensions, | |
| -} from "@electric-sql/pglite"; | |
| -import { electricSync } from "@electric-sql/pglite-sync"; | |
| -import { live } from "@electric-sql/pglite/live"; | |
| -import { vector } from "@electric-sql/pglite/vector"; | |
| -import type { PGliteWorker } from "@electric-sql/pglite/worker"; | |
| - | |
| -export const PG_LITE_INITIAL_SYNC_COMPLETE = (entityId: number) => | |
| - `${entityId}-pg-lite-initial-sync-complete`; | |
| - | |
| -export type CustomPGlite = PGliteWorker & | |
| - PGliteInterfaceExtensions<{ | |
| - live: typeof live; | |
| - vector: typeof vector; | |
| - electric: ReturnType<typeof electricSync>; | |
| - }>; | |
| - | |
| -// https://github.com/electric-sql/pglite/blob/cab4ce64135a147f284ef5fa448ddcf17d22d666/packages/pglite/src/fs/opfs-ahp.ts | |
| -// const opfsAhpFs = new OpfsAhpFS("pglite-db", { | |
| -// // debug: true, | |
| -// }); | |
| - | |
| -const indexedDbFS = new IdbFs("pglite-db"); | |
| - | |
| -export const ERASE_OPFS_DB = async (db: PGliteInterface, entityId: number) => { | |
| - await db.close(); | |
| - const databases = await indexedDB.databases(); | |
| - for (const db of databases) { | |
| - if (db.name?.includes("pglite")) { | |
| - indexedDB.deleteDatabase(db.name); | |
| - } | |
| - } | |
| - | |
| - const opfs = await navigator.storage.getDirectory(); | |
| - if ("remove" in opfs) { | |
| - // @ts-expect-error remove is not yet in the type definition and not standardized. https://developer.mozilla.org/en-US/docs/Web/API/FileSystemHandle/remove | |
| - await opfs.remove({ recursive: true }); | |
| - } | |
| - localStorage.removeItem(PG_LITE_INITIAL_SYNC_COMPLETE(entityId)); | |
| - window.location.reload(); | |
| -}; | |
| - | |
| -// Decent reference at https://github.com/ToramCalculator-Team/ToramCalculator/blob/4bf557c219eb870746efa5c210d572885ddd7133/src/worker/PGlite.worker.ts#L100 | |
| -export const PGLITE_OPTIONS = { | |
| - relaxedDurability: true, | |
| - fs: indexedDbFS, | |
| - debug: 5 as DebugLevel, | |
| - extensions: { | |
| - live, | |
| - vector, | |
| - electric: electricSync({ | |
| - debug: true, | |
| - }), | |
| - }, | |
| -}; | |
| diff --git a/src/components/pg-lite/migration.ts b/src/components/pg-lite/migration.ts | |
| deleted file mode 100644 | |
| index 089ae2cd..00000000 | |
| --- a/src/components/pg-lite/migration.ts | |
| +++ /dev/null | |
| @@ -1,760 +0,0 @@ | |
| -type Migration = { | |
| - id: string; | |
| - script: string; | |
| -}; | |
| -const TRANSACTION_ITEM_COST_TYPE_MIGRATION = ` | |
| - DROP TABLE IF EXISTS transaction_item_cost_type CASCADE; | |
| - CREATE TABLE IF NOT EXISTS transaction_item_cost_type | |
| - ( | |
| - tict_type varchar(255) not null | |
| - primary key | |
| - );`; | |
| - | |
| -const COHORT_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort | |
| - ( | |
| - co_id bigint | |
| - primary key, | |
| - co_name text not null, | |
| - co_created_at timestamp with time zone default CURRENT_TIMESTAMP, | |
| - co_updated_at timestamp with time zone default CURRENT_TIMESTAMP, | |
| - co_migration_id text | |
| - unique | |
| - );`; | |
| - | |
| -const COHORT_ITEM_SIZE_UNIT_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_item_size_unit CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_item_size_unit | |
| - ( | |
| - cits_size_unit varchar(255) not null | |
| - constraint cohort_item_size_unit_pk | |
| - primary key | |
| - );`; | |
| - | |
| -const DEPARTMENT_GROUP_MIGRATION = ` | |
| - DROP TABLE IF EXISTS department_group CASCADE; | |
| - CREATE TABLE IF NOT EXISTS department_group | |
| - ( | |
| - dg_id bigint | |
| - primary key, | |
| - dg_cohort_id bigint not null | |
| - references cohort, | |
| - dg_name varchar(255) not null, | |
| - dg_created_at timestamp default now() not null, | |
| - dg_updated_at timestamp default now() not null, | |
| - dg_migration_id text, | |
| - constraint department_group_unique_name | |
| - unique (dg_cohort_id, dg_name), | |
| - constraint department_group_migration_id_key | |
| - unique (dg_cohort_id, dg_migration_id) | |
| - );`; | |
| - | |
| -const DEPARTMENT_MIGRATION = ` | |
| - DROP TABLE IF EXISTS department CASCADE; | |
| - CREATE TABLE IF NOT EXISTS department | |
| - ( | |
| - dp_name varchar(255) not null, | |
| - dp_tax numeric(38, 6) not null | |
| - constraint department_tax_no_nan | |
| - check (dp_tax <> 'NaN'::numeric), | |
| - dp_bottledeposit numeric(38, 2) not null | |
| - constraint department_bottledeposit_no_nan | |
| - check (dp_bottledeposit <> 'NaN'::numeric), | |
| - dp_environmentfee numeric(38, 2) not null | |
| - constraint department_environmentfee_no_nan | |
| - check (dp_environmentfee <> 'NaN'::numeric), | |
| - dp_updated_at timestamp with time zone default now() not null, | |
| - dp_id bigint | |
| - primary key, | |
| - dp_cohort_id bigint | |
| - references cohort | |
| - on delete cascade, | |
| - dp_has_revenue boolean default true not null, | |
| - dp_department_group_id bigint not null | |
| - references department_group, | |
| - dp_migration_id text, | |
| - constraint department_pk | |
| - unique (dp_cohort_id, dp_name), | |
| - constraint department_migration_id_key | |
| - unique (dp_cohort_id, dp_migration_id), | |
| - constraint gift_cert_no_tax | |
| - check (((dp_name)::text <> 'Gift Cert'::text) OR | |
| - ((dp_tax = (0)::numeric) AND (dp_bottledeposit = (0)::numeric) AND (dp_environmentfee = (0)::numeric))) | |
| - );`; | |
| - | |
| -const ITEM_TYPE_MIGRATION = ` | |
| - DROP TABLE IF EXISTS item_type CASCADE; | |
| - CREATE TABLE IF NOT EXISTS item_type | |
| - ( | |
| - it_id bigint | |
| - primary key, | |
| - it_type text not null | |
| - unique | |
| - );`; | |
| - | |
| -const COHORT_ITEM_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_item CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_item ( | |
| - ci_id bigint CONSTRAINT cohort_item_pk PRIMARY KEY, | |
| - ci_cohort_id bigint NOT NULL CONSTRAINT cohort_item_cohort_id_fk REFERENCES cohort ON UPDATE CASCADE ON DELETE RESTRICT, | |
| - ci_name varchar(255) NOT NULL, | |
| - ci_case_quantity integer DEFAULT 1 NOT NULL CONSTRAINT positive_case_quantity CHECK ((ci_case_quantity IS NULL) OR (ci_case_quantity >= 1)), | |
| - ci_size numeric(10, 4) CONSTRAINT cohort_item_size_no_nan CHECK (ci_size <> 'NaN'::numeric), | |
| - ci_size_unit varchar(255) CONSTRAINT cohort_item_cohort_item_size_unit_size_unit_fk REFERENCES cohort_item_size_unit, | |
| - ci_alcohol_by_volume varchar(255), | |
| - ci_deposit_multiplier integer NOT NULL, | |
| - ci_environment_fee_multiplier integer NOT NULL, | |
| - ci_parent_cohort_item_id bigint, | |
| - ci_parent_quantity NUMERIC(12, 6), | |
| - ci_notes text, | |
| - ci_changed_by varchar(255), | |
| - ci_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - ci_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - ci_migration_id varchar(255), | |
| - ci_parent_migration_id varchar(255), | |
| - ci_department bigint NOT NULL CONSTRAINT cohort_item_department_id_fk REFERENCES department ON UPDATE CASCADE, | |
| - ci_brand varchar(255), | |
| - ci_pack_size integer CONSTRAINT positive_pack_size CHECK ((ci_pack_size IS NULL) OR (ci_pack_size >= 0)), | |
| - ci_alcoholic boolean DEFAULT TRUE NOT NULL, | |
| - ci_vintage varchar(255), | |
| - ci_item_type_id bigint NOT NULL REFERENCES item_type, | |
| - ci_version bigint DEFAULT 1 NOT NULL, | |
| - CONSTRAINT cohort_item_pk_2 UNIQUE (ci_cohort_id, ci_migration_id), | |
| - CONSTRAINT valid_parent_item CHECK ((ci_parent_cohort_item_id IS NULL) OR ((ci_parent_cohort_item_id IS NOT NULL) AND (ci_parent_quantity IS NOT NULL) AND (ci_parent_quantity > 0))), | |
| - CONSTRAINT valid_size CHECK ((ci_size IS NULL) OR ((ci_size IS NOT NULL) AND (ci_size_unit IS NOT NULL))) | |
| - );`; | |
| - | |
| -const COHORT_VENDOR_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_vendor CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_vendor ( | |
| - cv_id bigint CONSTRAINT cohort_vendor_pk PRIMARY KEY, | |
| - cv_cohort_id bigint NOT NULL CONSTRAINT cohort_vendor_cohort_id_fk REFERENCES cohort ON UPDATE CASCADE ON DELETE RESTRICT, | |
| - cv_vendor_id text NOT NULL, | |
| - cv_vendor_name text NOT NULL, | |
| - cv_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - cv_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - cv_changed_by text, | |
| - cv_email text, | |
| - cv_phone_number text, | |
| - cv_migration_id text, | |
| - cv_is_exclusive boolean DEFAULT FALSE NOT NULL, | |
| - CONSTRAINT cohort_vendor_pk_2 UNIQUE (cv_cohort_id, cv_migration_id) | |
| - );`; | |
| - | |
| -const COHORT_ITEM_VINTAGE_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_item_vintage CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_item_vintage ( | |
| - civ_id varchar(255) NOT NULL CONSTRAINT cohort_item_vintage_pk PRIMARY KEY, | |
| - civ_cohort_item_id bigint NOT NULL CONSTRAINT cohort_item_vintage_cohort_item_id_fk REFERENCES cohort_item ON UPDATE CASCADE ON DELETE CASCADE, | |
| - civ_vintage text NOT NULL, | |
| - civ_rating text, | |
| - civ_reviewer text, | |
| - civ_note text, | |
| - civ_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - civ_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - civ_version bigint DEFAULT 1 NOT NULL, | |
| - civ_reviewer_code text, | |
| - civ_cohort_id bigint CONSTRAINT cohort_item_vintage_cohort_id_fk REFERENCES cohort, | |
| - CONSTRAINT cohort_item_vintage_pk_2 UNIQUE (civ_cohort_item_id, civ_vintage) | |
| - );`; | |
| - | |
| -const ADDRESS_MIGRATION = ` | |
| - DROP TABLE IF EXISTS address CASCADE; | |
| - CREATE TABLE address | |
| - ( | |
| - adr_id varchar(255) not null | |
| - primary key, | |
| - adr_line1 text not null, | |
| - adr_line2 text, | |
| - adr_city text not null, | |
| - adr_state text not null, | |
| - adr_country text not null, | |
| - adr_postal_code text not null, | |
| - adr_created_at timestamp with time zone default now() not null, | |
| - adr_updated_at timestamp with time zone default now() not null | |
| - );`; | |
| - | |
| -const ENTITY_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity CASCADE; | |
| - | |
| - | |
| - CREATE TABLE IF NOT EXISTS entity ( | |
| - ey_name varchar(255), | |
| - ey_id bigint NOT NULL CONSTRAINT entity_pk PRIMARY KEY, | |
| - ey_credit_card_merchant_application_id varchar(255), | |
| - ey_credit_card_merchant_id varchar(255), | |
| - ey_address varchar(255) NOT NULL, | |
| - ey_fintech_host varchar(255), | |
| - ey_fintech_user varchar(255), | |
| - ey_fintech_passwd varchar(255), | |
| - ey_fintech_path varchar(255), | |
| - ey_payment_processor text, | |
| - ey_payment_fee_fixed numeric(8, 4) DEFAULT 0.10 NOT NULL CONSTRAINT entity_payment_fee_fixed_no_nan CHECK (ey_payment_fee_fixed <> 'NaN'::numeric), | |
| - ey_payment_fee_percent numeric(7, 4) DEFAULT 1.80 NOT NULL CONSTRAINT entity_payment_fee_percent_no_nan CHECK (ey_payment_fee_percent <> 'NaN'::numeric), | |
| - ey_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - ey_phone_number text, | |
| - ey_cohort_id bigint NOT NULL CONSTRAINT entity_cohort_id_fk REFERENCES cohort ON UPDATE CASCADE, | |
| - ey_location_id text, | |
| - ey_timezone text DEFAULT 'America/New_York'::text NOT NULL, | |
| - ey_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - ey_card_not_present_payment_fee_fixed numeric(10, 4) NOT NULL CONSTRAINT entity_card_not_present_payment_fee_fixed_no_nan CHECK (ey_card_not_present_payment_fee_fixed <> 'NaN'::numeric), | |
| - ey_card_not_present_payment_fee_percent numeric(10, 4) NOT NULL CONSTRAINT entity_card_not_present_payment_fee_percent_no_nan CHECK (ey_card_not_present_payment_fee_percent <> 'NaN'::numeric), | |
| - ey_surcharge_fee boolean NOT NULL, | |
| - ey_credit_card_merchant_token text, | |
| - ey_credit_card_terminal_id text, | |
| - ey_credit_card_merchant_online_id text, | |
| - ey_short_name text, | |
| - ey_transaction_item_cost_type varchar(255) NOT NULL REFERENCES transaction_item_cost_type, | |
| - ey_email text, | |
| - ey_address_id varchar(255) | |
| - constraint entity_address_id_fk | |
| - references address | |
| - on update cascade on delete restrict, | |
| - CONSTRAINT credit_card_processor_stripe CHECK ((ey_payment_processor IS NULL) OR (ey_payment_processor <> 'stripe'::text) OR ((ey_credit_card_merchant_application_id IS NOT NULL) AND (ey_credit_card_merchant_id IS NOT NULL) AND (ey_payment_fee_fixed IS NOT NULL) AND (ey_payment_fee_percent IS NOT NULL))), | |
| - CONSTRAINT fintech_onboarded CHECK ((ey_fintech_host IS NULL) OR ((ey_fintech_host IS NOT NULL) AND (ey_fintech_passwd IS NOT NULL) AND (ey_fintech_user IS NOT NULL) AND (ey_fintech_path IS NOT NULL))) | |
| - ); | |
| - | |
| - ALTER TABLE entity | |
| - ADD COLUMN IF NOT EXISTS ey_minimum_price_source_type VARCHAR(255) | |
| - REFERENCES entity_minimum_price_source_type(empst_type); | |
| -`; | |
| - | |
| -const ENTITY_ITEM_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity_item CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_item ( | |
| - ei_id bigint PRIMARY KEY, | |
| - ei_entity_id bigint NOT NULL, | |
| - ei_cohort_item_id bigint NOT NULL CONSTRAINT entity_item_cohort_item_id_fk REFERENCES cohort_item ON UPDATE CASCADE ON DELETE CASCADE, | |
| - ei_price numeric(10, 2) NOT NULL CONSTRAINT entity_item_price_no_nan CHECK (ei_price <> 'NaN'::numeric), | |
| - ei_minimum_price numeric(10, 2) CONSTRAINT entity_item_minimum_price_no_nan CHECK (ei_minimum_price <> 'NaN'::numeric), | |
| - ei_cost NUMERIC(10, 2) CONSTRAINT entity_item_cost_no_nan CHECK (ei_cost <> 'NaN'::numeric), | |
| - ei_discount_allowed boolean DEFAULT TRUE NOT NULL, | |
| - ei_quantity numeric(10, 4) DEFAULT 0 NOT NULL CONSTRAINT entity_item_quantity_no_nan CHECK (ei_quantity <> 'NaN'::numeric), | |
| - ei_aisle_location text, | |
| - ei_fridge_location text, | |
| - ei_last_quantity_received integer, | |
| - ei_changed_by varchar(255), | |
| - ei_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - ei_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - ei_migration_id varchar(255), | |
| - ei_last_order_date timestamp with time zone, | |
| - ei_exclusive boolean NOT NULL, | |
| - ei_case_cost numeric(10, 2) CONSTRAINT entity_item_case_cost_no_nan CHECK (ei_case_cost <> 'NaN'::numeric), | |
| - ei_variable_cost_percent numeric(10, 2) CONSTRAINT entity_item_variable_cost_percent_no_nan CHECK (ei_variable_cost_percent <> 'NaN'::numeric), | |
| - ei_last_cohort_vendor_id bigint CONSTRAINT entity_item_cohort_vendor_id_fk REFERENCES cohort_vendor ON UPDATE CASCADE, | |
| - ei_preferred_cohort_vendor_id bigint CONSTRAINT entity_item_cohort_vendor_id_fk_2 REFERENCES cohort_vendor ON UPDATE CASCADE, | |
| - ei_average_cost numeric(10, 4) CONSTRAINT entity_item_average_cost_no_nan CHECK (ei_average_cost <> 'NaN'::numeric), | |
| - ei_sellable boolean NOT NULL, | |
| - ei_version bigint DEFAULT 1 NOT NULL, | |
| - ei_cohort_item_vintage_id varchar(255) CONSTRAINT entity_item_cohort_item_vintage_id_fk REFERENCES cohort_item_vintage ON UPDATE CASCADE, | |
| - ei_true_cost numeric(10, 2), | |
| - CONSTRAINT entity_item_pk2 UNIQUE (ei_entity_id, ei_migration_id), | |
| - CONSTRAINT entity_item_pk3 UNIQUE (ei_entity_id, ei_cohort_item_id) | |
| - ); | |
| - | |
| - CREATE INDEX IF NOT EXISTS entity_item_cohort_item_id_index ON entity_item (ei_cohort_item_id); | |
| - | |
| - CREATE INDEX IF NOT EXISTS entity_item_vintage_index ON entity_item (ei_cohort_item_vintage_id); | |
| - | |
| - ALTER TABLE entity_item | |
| - DROP CONSTRAINT IF EXISTS entity_item_entity_id_fk; | |
| - | |
| - ALTER TABLE entity_item | |
| - ADD CONSTRAINT entity_item_entity_id_fk FOREIGN KEY (ei_entity_id) REFERENCES entity;`; | |
| - | |
| -const ENTITY_TAG_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity_tag CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_tag ( | |
| - et_id serial PRIMARY KEY, | |
| - et_name text NOT NULL, | |
| - et_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - et_cohort_id bigint NOT NULL CONSTRAINT entity_tag_cohort_id_fk REFERENCES cohort ON UPDATE CASCADE ON DELETE CASCADE, | |
| - et_migration_id text, | |
| - CONSTRAINT entity_tag_pk2 UNIQUE (et_cohort_id, et_name), | |
| - CONSTRAINT entity_tag_migration_id_key UNIQUE (et_cohort_id, et_migration_id) | |
| - );`; | |
| - | |
| -const ENTITY_ATTRIBUTE_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity_attribute CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_attribute ( | |
| - eattr_id text NOT NULL CONSTRAINT entity_attribute_pk PRIMARY KEY CONSTRAINT check_name CHECK (eattr_id = UPPER(eattr_id)), | |
| - eattr_description text | |
| - );`; | |
| - | |
| -const ENTITY_CONFIGURATION_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity_configuration CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_configuration ( | |
| - ecfg_entity_id bigint NOT NULL CONSTRAINT entity_configuration_entity_id_fk REFERENCES entity ON UPDATE CASCADE ON DELETE CASCADE, | |
| - ecfg_attribute_id text NOT NULL CONSTRAINT entity_configuration_entity_attribute_id_fk REFERENCES entity_attribute ON UPDATE CASCADE ON DELETE CASCADE, | |
| - ecfg_value text NOT NULL, | |
| - CONSTRAINT entity_configuration_pk PRIMARY KEY (ecfg_entity_id, ecfg_attribute_id) | |
| - );`; | |
| - | |
| -const REGISTER_MIGRATION = ` | |
| - DROP TABLE IF EXISTS register CASCADE; | |
| - CREATE TABLE IF NOT EXISTS register ( | |
| - reg_entity_id bigint NOT NULL CONSTRAINT register_entity_id_fk REFERENCES entity ON UPDATE CASCADE ON DELETE CASCADE, | |
| - reg_register_number bigint NOT NULL, | |
| - reg_credit_card_device_id varchar(255), | |
| - reg_updated_at timestamp with time zone DEFAULT NOW(), | |
| - PRIMARY KEY (reg_entity_id, reg_register_number) | |
| - );`; | |
| - | |
| -const BILL_DENOMINATION_MIGRATION = ` | |
| - DROP TABLE IF EXISTS bill_denomination CASCADE; | |
| - CREATE TABLE IF NOT EXISTS bill_denomination ( | |
| - bd_denomination_dollar_value numeric(10, 4) NOT NULL PRIMARY KEY CONSTRAINT bill_denomination_denomination_dollar_value_no_nan CHECK (bd_denomination_dollar_value <> 'NaN'::numeric), | |
| - bd_denomination_type text NOT NULL | |
| - );`; | |
| - | |
| -const SALES_CHANNEL_TYPE_MIGRATION = ` | |
| - DROP TABLE IF EXISTS sales_channel_type CASCADE; | |
| - CREATE TABLE IF NOT EXISTS sales_channel_type ( | |
| - sct_id bigint PRIMARY KEY, | |
| - sct_name varchar(255) NOT NULL CONSTRAINT sales_channel_type_name_unique UNIQUE, | |
| - sct_description text, | |
| - sct_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - sct_config jsonb | |
| - );`; | |
| - | |
| -const COHORT_PRICE_LEVEL_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_price_level CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_price_level ( | |
| - cpl_id bigint PRIMARY KEY, | |
| - cpl_cohort_id bigint NOT NULL REFERENCES cohort ON DELETE CASCADE, | |
| - cpl_name text NOT NULL, | |
| - cpl_markup_percent numeric(10, 4) NOT NULL CONSTRAINT cohort_price_level_markup_percent_no_nan CHECK (cpl_markup_percent <> 'NaN'::numeric), | |
| - cpl_markup_cohort_price_level_id bigint REFERENCES cohort_price_level ON UPDATE CASCADE ON DELETE RESTRICT, | |
| - cpl_migration_id text, | |
| - CONSTRAINT unique_cohort_price_level_name UNIQUE (cpl_cohort_id, cpl_name), | |
| - CONSTRAINT cohort_price_level_migration_id_key UNIQUE (cpl_cohort_id, cpl_migration_id) | |
| - );`; | |
| - | |
| -const ENTITY_SALES_CHANNEL_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity_sales_channel CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_sales_channel ( | |
| - esc_id bigint PRIMARY KEY, | |
| - esc_sales_channel_type_id bigint NOT NULL CONSTRAINT sales_channel_type_fk REFERENCES sales_channel_type, | |
| - esc_entity_id bigint NOT NULL CONSTRAINT entity_fk REFERENCES entity, | |
| - esc_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - esc_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - esc_account_id text, | |
| - esc_active boolean DEFAULT FALSE NOT NULL, | |
| - esc_external_location_id text, | |
| - esc_name text NOT NULL, | |
| - esc_taxable boolean DEFAULT TRUE NOT NULL, | |
| - esc_price_level_id bigint REFERENCES cohort_price_level ON UPDATE CASCADE ON DELETE RESTRICT, | |
| - esc_external_integration_enabled boolean DEFAULT FALSE NOT NULL, | |
| - esc_external_integration_attempt integer DEFAULT 0 NOT NULL, | |
| - esc_external_address_line_1 text, | |
| - esc_external_address_line_2 text, | |
| - esc_external_address_city text, | |
| - esc_external_address_state text, | |
| - esc_external_address_zip text, | |
| - esc_external_requestor_name text, | |
| - esc_external_requestor_email text, | |
| - esc_external_merchant_decision_maker_email text, | |
| - esc_sftp_credentials jsonb, | |
| - esc_configuration jsonb, | |
| - esc_auto_add_new_departments boolean DEFAULT TRUE NOT NULL, | |
| - esc_allow_negative_inventory boolean DEFAULT FALSE | |
| - ); | |
| - | |
| - CREATE INDEX IF NOT EXISTS entity_sales_channel_type_index ON entity_sales_channel (esc_sales_channel_type_id); | |
| - | |
| - CREATE INDEX IF NOT EXISTS entity_sales_channel_price_level_id_idx ON entity_sales_channel (esc_price_level_id); | |
| - | |
| - CREATE INDEX IF NOT EXISTS entity_sales_channel_sales_channel_type_id_idx ON entity_sales_channel (esc_sales_channel_type_id); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS entity_sales_channel_entity_id_sales_channel_type_id_uindex ON entity_sales_channel (esc_entity_id, esc_sales_channel_type_id) | |
| - WHERE (esc_sales_channel_type_id = ANY (ARRAY[(1)::bigint, (3)::bigint, (4)::bigint, (6)::bigint, (7)::bigint, (8)::bigint, (9)::bigint, (10)::bigint, (13)::bigint, (14)::bigint, (18)::bigint, (17)::bigint]));`; | |
| - | |
| -const COHORT_ITEM_TAG_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_item_tag CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_item_tag ( | |
| - cit_id bigint CONSTRAINT cohort_item_tag_pk PRIMARY KEY, | |
| - cit_cohort_item_id bigint NOT NULL CONSTRAINT cohort_item_tag_cohort_item_id_fk REFERENCES cohort_item ON UPDATE CASCADE ON DELETE CASCADE, | |
| - cit_tag_id integer NOT NULL CONSTRAINT cohort_item_tag_tag_id_fk REFERENCES entity_tag ON UPDATE CASCADE ON DELETE CASCADE, | |
| - cit_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - cit_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - cit_changed_by varchar(255), | |
| - cit_cohort_id bigint CONSTRAINT cohort_item_tag_cohort_id_fk REFERENCES cohort, | |
| - CONSTRAINT cohort_item_tag_pk_2 UNIQUE (cit_cohort_item_id, cit_tag_id) | |
| - );`; | |
| - | |
| -const COHORT_ITEM_BARCODE_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_item_barcode CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_item_barcode ( | |
| - cib_cohort_item_id bigint NOT NULL CONSTRAINT cohort_item_barcode_cohort_item_id_fk REFERENCES cohort_item ON UPDATE CASCADE ON DELETE CASCADE, | |
| - cib_barcode varchar(255) NOT NULL, | |
| - cib_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - cib_cohort_id bigint CONSTRAINT cohort_item_barcode_cohort_id_fk REFERENCES cohort, | |
| - CONSTRAINT cohort_item_barcode_pk PRIMARY KEY (cib_cohort_item_id, cib_barcode) | |
| - );`; | |
| - | |
| -const COHORT_ITEM_VENDOR_ITEM_MIGRATION = ` | |
| - DROP TABLE IF EXISTS cohort_item_vendor_item CASCADE; | |
| - CREATE TABLE IF NOT EXISTS cohort_item_vendor_item ( | |
| - civi_cohort_item_id bigint NOT NULL CONSTRAINT cohort_item_vendor_item_cohort_item_id_fk REFERENCES cohort_item ON UPDATE CASCADE ON DELETE CASCADE, | |
| - civi_vendor varchar(255) NOT NULL, | |
| - civi_sku varchar(255), | |
| - civi_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - civi_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - civi_changed_by varchar(255), | |
| - civi_cohort_vendor_id bigint NOT NULL CONSTRAINT cohort_item_vendor_item_cohort_vendor_id_fk REFERENCES cohort_vendor ON UPDATE CASCADE, | |
| - civi_cohort_id bigint CONSTRAINT cohort_item_vendor_item_cohort_id_fk REFERENCES cohort, | |
| - CONSTRAINT cohort_item_vendor_item_pk PRIMARY KEY (civi_cohort_item_id, civi_cohort_vendor_id) | |
| - );`; | |
| - | |
| -const ENTITY_SALES_CHANNEL_ITEM_MIGRATION = ` | |
| - DROP TABLE IF EXISTS entity_sales_channel_item CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_sales_channel_item ( | |
| - esci_id bigint PRIMARY KEY, | |
| - esci_entity_sales_channel_id bigint NOT NULL CONSTRAINT entity_sales_channel_fk REFERENCES entity_sales_channel, | |
| - esci_entity_item_id bigint NOT NULL CONSTRAINT entity_item_fk REFERENCES entity_item ON UPDATE CASCADE ON DELETE CASCADE, | |
| - esci_active boolean DEFAULT TRUE NOT NULL, | |
| - esci_created_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - esci_updated_at timestamp with time zone DEFAULT NOW() NOT NULL, | |
| - esci_external_item_id text, | |
| - esci_entity_id bigint CONSTRAINT entity_sales_channel_item_entity_id_fk REFERENCES entity, | |
| - CONSTRAINT entity_sales_channel_item_external_item_id_unique UNIQUE (esci_entity_sales_channel_id, esci_external_item_id), | |
| - CONSTRAINT unique_entity_sales_channel_item UNIQUE (esci_entity_sales_channel_id, esci_entity_item_id) | |
| - );`; | |
| - | |
| -const CASBIN_MIGRATION = ` | |
| - CREATE TABLE IF NOT EXISTS casbin_rule_role ( | |
| - crr_id serial PRIMARY KEY, | |
| - crr_ptype varchar(100) NOT NULL, | |
| - crr_v0 varchar(100), | |
| - crr_v1 varchar(100), | |
| - crr_v2 varchar(100), | |
| - crr_v3 varchar(100), | |
| - crr_v4 varchar(100), | |
| - crr_v5 varchar(100), | |
| - CONSTRAINT ptype_is_p_v1_number CHECK (((crr_ptype)::text <> 'p'::text) OR ((crr_v1 IS NOT NULL) AND ((crr_v1)::text ~ '^[0-9]+$'::text))) | |
| - ); | |
| - | |
| - CREATE TABLE IF NOT EXISTS casbin_rule_user ( | |
| - cru_id serial PRIMARY KEY, | |
| - cru_ptype varchar(100) NOT NULL, | |
| - cru_v0 varchar(100), | |
| - cru_v1 varchar(100), | |
| - cru_v2 varchar(100), | |
| - cru_v3 varchar(100), | |
| - cru_v4 varchar(100), | |
| - cru_v5 varchar(100), | |
| - CONSTRAINT ptype_is_p_v1_number CHECK (((cru_ptype)::text <> 'p'::text) OR ((cru_v1 IS NOT NULL) AND ((cru_v1)::text ~ '^[0-9]+$'::text))) | |
| - ); | |
| - | |
| - CREATE INDEX IF NOT EXISTS casbin_rule_v0_index ON casbin_rule_role (crr_v0); | |
| - | |
| - CREATE INDEX IF NOT EXISTS casbin_rule_v1_index ON casbin_rule_role (crr_v1); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS casbin_rule_v0_v2_uindex ON casbin_rule_role (crr_v0, crr_v2) | |
| - WHERE ((crr_ptype)::text = 'g'::text); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS casbin_rule_v2_uindex ON casbin_rule_role (crr_v2) | |
| - WHERE (((crr_ptype)::text = 'g'::text) AND ((crr_v1)::text = 'OWNER'::text)); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS casbin_rule_pos_register_uindex ON casbin_rule_role (crr_v0, crr_v1) | |
| - WHERE (((crr_ptype)::text = 'g'::text) AND ((crr_v1)::text = 'POS_REGISTER'::text)); | |
| - | |
| - CREATE INDEX IF NOT EXISTS casbin_rule_v0_index ON casbin_rule_user (cru_v0); | |
| - | |
| - CREATE INDEX IF NOT EXISTS casbin_rule_v1_index ON casbin_rule_user (cru_v1); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS casbin_rule_v0_v2_uindex ON casbin_rule_user (cru_v0, cru_v2) | |
| - WHERE ((cru_ptype)::text = 'g'::text); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS casbin_rule_v2_uindex ON casbin_rule_user (cru_v2) | |
| - WHERE (((cru_ptype)::text = 'g'::text) AND ((cru_v1)::text = 'OWNER'::text)); | |
| - | |
| - CREATE UNIQUE INDEX IF NOT EXISTS casbin_rule_pos_register_uindex ON casbin_rule_user (cru_v0, cru_v1) | |
| - WHERE (((cru_ptype)::text = 'g'::text) AND ((cru_v1)::text = 'POS_REGISTER'::text)); | |
| -`; | |
| - | |
| -const ENTITY_MINIMUM_PRICE_SOURCE_TYPE = ` | |
| - DROP TABLE IF EXISTS entity_minimum_price_source_type CASCADE; | |
| - CREATE TABLE IF NOT EXISTS entity_minimum_price_source_type ( | |
| - empst_type VARCHAR(255) NOT NULL CONSTRAINT entity_minimum_price_source_type_pk PRIMARY KEY | |
| - ); | |
| -`; | |
| - | |
| -const ENTITY_ADDRESS_NULLABLE_MIGRATION = ` | |
| - ALTER TABLE entity | |
| - ALTER COLUMN ey_address DROP NOT NULL; | |
| -`; | |
| - | |
| -const COHORT_ID_SYNC_MIGRATION_CIB_ESCI_CIVIN_CIVI_CIT = ` | |
| - -- Department Group | |
| - ALTER TABLE department_group | |
| - DROP CONSTRAINT IF EXISTS department_group_cohort_id_id_key; | |
| - | |
| - ALTER TABLE department_group | |
| - ADD CONSTRAINT department_group_cohort_id_id_key UNIQUE (dg_cohort_id, dg_id); | |
| - | |
| - -- Department | |
| - ALTER TABLE department | |
| - DROP CONSTRAINT IF EXISTS department_cohort_id_id_key; | |
| - | |
| - ALTER TABLE department | |
| - ADD CONSTRAINT department_cohort_id_id_key UNIQUE (dp_cohort_id, dp_id); | |
| - | |
| - DROP INDEX IF EXISTS department_department_group_id_index; | |
| - | |
| - ALTER TABLE department | |
| - DROP CONSTRAINT IF EXISTS department_department_group_id_fkey; | |
| - | |
| - DROP INDEX IF EXISTS department_cohort_id_department_group_id_index; | |
| - | |
| - CREATE INDEX department_cohort_id_department_group_id_index ON department (dp_cohort_id, dp_department_group_id); | |
| - | |
| - ALTER TABLE department | |
| - DROP CONSTRAINT IF EXISTS department_department_group_cohort_id_id_fk; | |
| - | |
| - ALTER TABLE department | |
| - ADD CONSTRAINT department_department_group_cohort_id_id_fk FOREIGN KEY (dp_cohort_id, dp_department_group_id) REFERENCES department_group (dg_cohort_id, dg_id) ON UPDATE CASCADE; | |
| - | |
| - -- Cohort Item | |
| - ALTER TABLE cohort_item | |
| - DROP CONSTRAINT IF EXISTS cohort_item_department_id_fk; | |
| - | |
| - ALTER TABLE cohort_item | |
| - DROP CONSTRAINT IF EXISTS cohort_item_department_cohort_id_id_fk; | |
| - | |
| - ALTER TABLE cohort_item | |
| - ADD CONSTRAINT cohort_item_department_cohort_id_id_fk FOREIGN KEY (ci_cohort_id, ci_department) REFERENCES department (dp_cohort_id, dp_id) ON UPDATE CASCADE; | |
| - | |
| - ALTER TABLE cohort_item | |
| - DROP CONSTRAINT IF EXISTS cohort_item_cohort_id_id_key; | |
| - | |
| - ALTER TABLE cohort_item | |
| - ADD CONSTRAINT cohort_item_cohort_id_id_key UNIQUE (ci_cohort_id, ci_id); | |
| - | |
| - -- Cohort Item Barcode | |
| - ALTER TABLE cohort_item_barcode | |
| - ALTER COLUMN cib_cohort_id SET NOT NULL; | |
| - | |
| - ALTER TABLE cohort_item_barcode | |
| - DROP CONSTRAINT IF EXISTS cohort_item_barcode_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_barcode | |
| - DROP CONSTRAINT IF EXISTS cohort_item_barcode_cohort_id_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_barcode | |
| - ADD CONSTRAINT cohort_item_barcode_cohort_id_cohort_item_id_fk FOREIGN KEY (cib_cohort_id, cib_cohort_item_id) REFERENCES cohort_item (ci_cohort_id, ci_id) ON UPDATE CASCADE ON DELETE CASCADE; | |
| - | |
| - -- Tag | |
| - ALTER TABLE entity_tag | |
| - DROP CONSTRAINT IF EXISTS entity_tag_cohort_id_id_key; | |
| - | |
| - ALTER TABLE entity_tag | |
| - ADD CONSTRAINT entity_tag_cohort_id_id_key UNIQUE (et_cohort_id, et_id); | |
| - | |
| - -- Cohort Item Tag | |
| - ALTER TABLE cohort_item_tag | |
| - ALTER COLUMN cit_cohort_id SET NOT NULL; | |
| - | |
| - ALTER TABLE cohort_item_tag | |
| - DROP CONSTRAINT IF EXISTS cohort_item_tag_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_tag | |
| - DROP CONSTRAINT IF EXISTS cohort_item_tag_cohort_id_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_tag | |
| - ADD CONSTRAINT cohort_item_tag_cohort_id_cohort_item_id_fk FOREIGN KEY (cit_cohort_id, cit_cohort_item_id) REFERENCES cohort_item (ci_cohort_id, ci_id) ON UPDATE CASCADE ON DELETE CASCADE; | |
| - | |
| - ALTER TABLE cohort_item_tag | |
| - DROP CONSTRAINT IF EXISTS cohort_item_tag_tag_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_tag | |
| - DROP CONSTRAINT IF EXISTS cohort_item_tag_cohort_id_tag_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_tag | |
| - ADD CONSTRAINT cohort_item_tag_cohort_id_tag_id_fk FOREIGN KEY (cit_cohort_id, cit_tag_id) REFERENCES entity_tag (et_cohort_id, et_id) ON UPDATE CASCADE ON DELETE CASCADE; | |
| - | |
| - -- Cohort Item Vendor Item | |
| - ALTER TABLE cohort_item_vendor_item | |
| - ALTER COLUMN civi_cohort_id SET NOT NULL; | |
| - | |
| - ALTER TABLE cohort_item_vendor_item | |
| - DROP CONSTRAINT IF EXISTS cohort_item_vendor_item_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_vendor_item | |
| - DROP CONSTRAINT IF EXISTS cohort_item_vendor_item_cohort_item_id_cohort_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_vendor_item | |
| - DROP CONSTRAINT IF EXISTS cohort_item_vendor_item_cohort_id_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_vendor_item | |
| - ADD CONSTRAINT cohort_item_vendor_item_cohort_id_cohort_item_id_fk FOREIGN KEY (civi_cohort_id, civi_cohort_item_id) REFERENCES cohort_item (ci_cohort_id, ci_id) ON UPDATE CASCADE ON DELETE CASCADE; | |
| - | |
| - -- Cohort Item Vintage | |
| - ALTER TABLE cohort_item_vintage | |
| - ALTER COLUMN civ_cohort_id SET NOT NULL; | |
| - | |
| - ALTER TABLE cohort_item_vintage | |
| - DROP CONSTRAINT IF EXISTS cohort_item_vintage_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_vintage | |
| - DROP CONSTRAINT IF EXISTS cohort_item_vintage_cohort_item_id_cohort_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_vintage | |
| - DROP CONSTRAINT IF EXISTS cohort_item_vintage_cohort_id_cohort_item_id_fk; | |
| - | |
| - ALTER TABLE cohort_item_vintage | |
| - ADD CONSTRAINT cohort_item_vintage_cohort_id_cohort_item_id_fk FOREIGN KEY (civ_cohort_id, civ_cohort_item_id) REFERENCES cohort_item (ci_cohort_id, ci_id) ON UPDATE CASCADE ON DELETE CASCADE; | |
| - | |
| - -- Entity Item | |
| - ALTER TABLE entity_item | |
| - DROP CONSTRAINT IF EXISTS entity_item_entity_id_id_key; | |
| - | |
| - ALTER TABLE entity_item | |
| - ADD CONSTRAINT entity_item_entity_id_id_key UNIQUE (ei_entity_id, ei_id); | |
| - | |
| - -- Entity Sales Channel | |
| - ALTER TABLE entity_sales_channel | |
| - DROP CONSTRAINT IF EXISTS entity_sales_channel_entity_id_id_key; | |
| - | |
| - ALTER TABLE entity_sales_channel | |
| - ADD CONSTRAINT entity_sales_channel_entity_id_id_key UNIQUE (esc_entity_id, esc_id); | |
| - | |
| - -- Entity Sales Channel Item | |
| - ALTER TABLE entity_sales_channel_item | |
| - ALTER COLUMN esci_entity_id SET NOT NULL; | |
| - | |
| - DROP INDEX IF EXISTS entity_sales_channel_item_entity_item_id_index; | |
| - | |
| - DROP INDEX IF EXISTS entity_sales_channel_item_entity_id_entity_item_id_index; | |
| - | |
| - CREATE INDEX entity_sales_channel_item_entity_id_entity_item_id_index ON entity_sales_channel_item (esci_entity_id, esci_entity_item_id); | |
| - | |
| - ALTER TABLE entity_sales_channel_item | |
| - DROP CONSTRAINT IF EXISTS entity_item_fk; | |
| - | |
| - ALTER TABLE entity_sales_channel_item | |
| - ADD CONSTRAINT entity_item_fk FOREIGN KEY (esci_entity_id, esci_entity_item_id) REFERENCES entity_item (ei_entity_id, ei_id) ON UPDATE CASCADE ON DELETE CASCADE; | |
| - | |
| - ALTER TABLE entity_sales_channel_item | |
| - DROP CONSTRAINT IF EXISTS entity_sales_channel_fk; | |
| - | |
| - ALTER TABLE entity_sales_channel_item | |
| - ADD CONSTRAINT entity_sales_channel_fk FOREIGN KEY (esci_entity_id, esci_entity_sales_channel_id) REFERENCES entity_sales_channel (esc_entity_id, esc_id); | |
| -`; | |
| - | |
| -export const MIGRATIONS: Migration[] = [ | |
| - { | |
| - id: "transaction_item_cost_type", | |
| - script: TRANSACTION_ITEM_COST_TYPE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort", | |
| - script: COHORT_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_item_size_unit", | |
| - script: COHORT_ITEM_SIZE_UNIT_MIGRATION, | |
| - }, | |
| - { | |
| - id: "department_group", | |
| - script: DEPARTMENT_GROUP_MIGRATION, | |
| - }, | |
| - { | |
| - id: "department", | |
| - script: DEPARTMENT_MIGRATION, | |
| - }, | |
| - { | |
| - id: "item_type", | |
| - script: ITEM_TYPE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_item", | |
| - script: COHORT_ITEM_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_vendor", | |
| - script: COHORT_VENDOR_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_minimum_price_source_type", | |
| - script: ENTITY_MINIMUM_PRICE_SOURCE_TYPE, | |
| - }, | |
| - { | |
| - id: "cohort_item_vintage", | |
| - script: COHORT_ITEM_VINTAGE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "address", | |
| - script: ADDRESS_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity", | |
| - script: ENTITY_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_item", | |
| - script: ENTITY_ITEM_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_tag", | |
| - script: ENTITY_TAG_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_attribute", | |
| - script: ENTITY_ATTRIBUTE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_configuration", | |
| - script: ENTITY_CONFIGURATION_MIGRATION, | |
| - }, | |
| - { | |
| - id: "register", | |
| - script: REGISTER_MIGRATION, | |
| - }, | |
| - { | |
| - id: "bill_denomination", | |
| - script: BILL_DENOMINATION_MIGRATION, | |
| - }, | |
| - { | |
| - id: "sales_channel_type", | |
| - script: SALES_CHANNEL_TYPE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_price_level", | |
| - script: COHORT_PRICE_LEVEL_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_sales_channel", | |
| - script: ENTITY_SALES_CHANNEL_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_item_tag", | |
| - script: COHORT_ITEM_TAG_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_item_barcode", | |
| - script: COHORT_ITEM_BARCODE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_item_vendor_item", | |
| - script: COHORT_ITEM_VENDOR_ITEM_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_sales_channel_item", | |
| - script: ENTITY_SALES_CHANNEL_ITEM_MIGRATION, | |
| - }, | |
| - { | |
| - id: "casbin", | |
| - script: CASBIN_MIGRATION, | |
| - }, | |
| - { | |
| - id: "entity_address_nullable", | |
| - script: ENTITY_ADDRESS_NULLABLE_MIGRATION, | |
| - }, | |
| - { | |
| - id: "cohort_id_sync_cib_esci_civin_civi_cit", | |
| - script: COHORT_ID_SYNC_MIGRATION_CIB_ESCI_CIVIN_CIVI_CIT, | |
| - }, | |
| - // Add more migrations here as needed | |
| -]; | |
| diff --git a/src/components/pg-lite/pglite-worker.ts b/src/components/pg-lite/pglite-worker.ts | |
| deleted file mode 100644 | |
| index b7c62e13..00000000 | |
| --- a/src/components/pg-lite/pglite-worker.ts | |
| +++ /dev/null | |
| @@ -1,42 +0,0 @@ | |
| -import { PGlite } from "@electric-sql/pglite"; | |
| -import { worker } from "@electric-sql/pglite/worker"; | |
| -import { MIGRATIONS } from "./migration"; | |
| -import { PGLITE_OPTIONS } from "./PgliteOptions"; | |
| - | |
| -void worker({ | |
| - async init() { | |
| - // Create and return a PGlite instance | |
| - const pg = await PGlite.create(PGLITE_OPTIONS); | |
| - | |
| - // Exempt from the migration convention | |
| - await pg.exec(` | |
| - CREATE TABLE IF NOT EXISTS migrations ( | |
| - id TEXT PRIMARY KEY, | |
| - applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| - ); | |
| - `); | |
| - await pg.exec(` | |
| - SET session_replication_role = 'replica'; | |
| - `); | |
| - for (const migration of MIGRATIONS) { | |
| - const res = await pg.query( | |
| - "SELECT 1 FROM migrations WHERE id = $1::text", | |
| - [migration.id], | |
| - ); | |
| - if (res.rows.length === 0) { | |
| - console.info(`Applying migration: ${migration.id}`); | |
| - await pg.transaction(async (tx) => { | |
| - await tx.exec(migration.script); | |
| - await tx.query( | |
| - "INSERT INTO migrations (id) VALUES ($1::text) ON CONFLICT DO NOTHING", | |
| - [migration.id], | |
| - ); | |
| - }); | |
| - } else { | |
| - console.info(`Migration already applied: ${migration.id}`); | |
| - } | |
| - } | |
| - | |
| - return pg; | |
| - }, | |
| -}); | |
| diff --git a/src/components/pg-lite/queries/RetrieveItemsByUpc.ts b/src/components/pg-lite/queries/RetrieveItemsByUpc.ts | |
| deleted file mode 100644 | |
| index 692d7eab..00000000 | |
| --- a/src/components/pg-lite/queries/RetrieveItemsByUpc.ts | |
| +++ /dev/null | |
| @@ -1,30 +0,0 @@ | |
| -import { query } from "@electric-sql/pglite/template"; | |
| -import { CohortItem } from "../table-types/CohortItem"; | |
| -import { Department } from "../table-types/Department"; | |
| -import { EntityItem } from "../table-types/EntityItem"; | |
| - | |
| -export type RetrieveItemsByUpc = CohortItem & EntityItem & Department; | |
| - | |
| -export const RetrieveItemsByUpcQuery = ( | |
| - entityId: number, | |
| - upc: string | null, | |
| - entityItemId: number[] | null, | |
| -) => query` | |
| - SELECT * FROM | |
| - entity_item ei | |
| - JOIN cohort_item ci ON ei.ei_cohort_item_id = ci.ci_id | |
| - JOIN department dp ON ci.ci_department = dp.dp_id | |
| - WHERE | |
| - ei.ei_entity_id = ${entityId} | |
| - AND ei.ei_sellable | |
| - AND (${upc}::text IS NULL OR EXISTS ( | |
| - SELECT | |
| - 1 | |
| - FROM | |
| - cohort_item_barcode cib | |
| - WHERE | |
| - cib.cib_cohort_item_id = ci.ci_id | |
| - AND cib.cib_barcode LIKE ${upc}::text)) | |
| - AND (${entityItemId}::BIGINT[] IS NULL OR ei.ei_id = ANY(${entityItemId})) | |
| - LIMIT 100 | |
| -`; | |
| diff --git a/src/components/pg-lite/table-types/CohortItem.ts b/src/components/pg-lite/table-types/CohortItem.ts | |
| deleted file mode 100644 | |
| index 71ee391c..00000000 | |
| --- a/src/components/pg-lite/table-types/CohortItem.ts | |
| +++ /dev/null | |
| @@ -1,28 +0,0 @@ | |
| -import { BigDecimal } from "src/big-decimal/BigDecimal"; | |
| - | |
| -export type CohortItem = { | |
| - ci_id: number; | |
| - ci_cohort_id: number; | |
| - ci_name: string; | |
| - ci_case_quantity: number; | |
| - ci_size: BigDecimal | null; // numeric(10, 4) | |
| - ci_size_unit: string | null; | |
| - ci_alcohol_by_volume: string | null; | |
| - ci_deposit_multiplier: number; | |
| - ci_environment_fee_multiplier: number; | |
| - ci_parent_cohort_item_id: number | null; | |
| - ci_parent_quantity: number | null; | |
| - ci_notes: string | null; | |
| - ci_changed_by: string | null; | |
| - ci_created_at: Date; | |
| - ci_updated_at: Date; | |
| - ci_migration_id: string | null; | |
| - ci_parent_migration_id: string | null; | |
| - ci_department: number; | |
| - ci_brand: string | null; | |
| - ci_pack_size: number | null; | |
| - ci_alcoholic: boolean; | |
| - ci_vintage: string | null; | |
| - ci_item_type_id: number; | |
| - ci_version: number; | |
| -}; | |
| diff --git a/src/components/pg-lite/table-types/Department.ts b/src/components/pg-lite/table-types/Department.ts | |
| deleted file mode 100644 | |
| index b348ad7b..00000000 | |
| --- a/src/components/pg-lite/table-types/Department.ts | |
| +++ /dev/null | |
| @@ -1,12 +0,0 @@ | |
| -export type Department = { | |
| - dp_name: string; | |
| - dp_tax: string; // numeric(38, 6) | |
| - dp_bottledeposit: string; // numeric(38, 2) | |
| - dp_environmentfee: string; // numeric(38, 2) | |
| - dp_updated_at: Date; | |
| - dp_id: number; | |
| - dp_cohort_id: number | null; | |
| - dp_has_revenue: boolean; | |
| - dp_department_group_id: number; | |
| - dp_migration_id: string | null; | |
| -}; | |
| diff --git a/src/components/pg-lite/table-types/EntityItem.ts b/src/components/pg-lite/table-types/EntityItem.ts | |
| deleted file mode 100644 | |
| index f42560ba..00000000 | |
| --- a/src/components/pg-lite/table-types/EntityItem.ts | |
| +++ /dev/null | |
| @@ -1,28 +0,0 @@ | |
| -export type EntityItem = { | |
| - ei_id: number; | |
| - ei_entity_id: number; | |
| - ei_cohort_item_id: number; | |
| - ei_price: string; // numeric(10, 2) | |
| - ei_minimum_price: string | null; // numeric(10, 2) | |
| - ei_cost: string | null; // numeric(10, 2) | |
| - ei_discount_allowed: boolean; | |
| - ei_quantity: string; // numeric(10, 4) | |
| - ei_aisle_location: string | null; | |
| - ei_fridge_location: string | null; | |
| - ei_last_quantity_received: number | null; | |
| - ei_changed_by: string | null; | |
| - ei_created_at: Date; | |
| - ei_updated_at: Date; | |
| - ei_migration_id: string | null; | |
| - ei_last_order_date: Date | null; | |
| - ei_exclusive: boolean; | |
| - ei_case_cost: string | null; // numeric(10, 2) | |
| - ei_variable_cost_percent: string | null; // numeric(10, 2) | |
| - ei_last_cohort_vendor_id: number | null; | |
| - ei_preferred_cohort_vendor_id: number | null; | |
| - ei_average_cost: string | null; // numeric(10, 4) | |
| - ei_sellable: boolean; | |
| - ei_version: number; | |
| - ei_cohort_item_vintage_id: string | null; | |
| - ei_true_cost: string | null; // numeric(10, 2) | |
| -}; | |
| diff --git a/src/components/po/PurchaseOrderCandidateItems.test.tsx b/src/components/po/PurchaseOrderCandidateItems.test.tsx | |
| index 1ca54336..d71113be 100644 | |
| --- a/src/components/po/PurchaseOrderCandidateItems.test.tsx | |
| +++ b/src/components/po/PurchaseOrderCandidateItems.test.tsx | |
| @@ -665,7 +665,6 @@ describe("Data Management Tests", () => { | |
| mockCaptureException(err); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| queryClient, | |
| mockPurchaseOrder.entities, | |
| @@ -733,7 +732,6 @@ describe("Data Management Tests", () => { | |
| mockCaptureException(err); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| queryClient, | |
| mockPurchaseOrder.entities, | |
| diff --git a/src/components/po/PurchaseOrderCandidateItems.tsx b/src/components/po/PurchaseOrderCandidateItems.tsx | |
| index 07d29afc..82c8ef14 100644 | |
| --- a/src/components/po/PurchaseOrderCandidateItems.tsx | |
| +++ b/src/components/po/PurchaseOrderCandidateItems.tsx | |
| @@ -239,7 +239,6 @@ export const PurchaseOrderCandidateItems = forwardRef< | |
| [queryClient, toast], | |
| ); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| const queueItemRefresh = useCallback( | |
| queue<CohortItem["id"]>(refreshItems, { | |
| wait: 0, | |
| diff --git a/src/components/po/PurchaseOrderItemCard.tsx b/src/components/po/PurchaseOrderItemCard.tsx | |
| index ebdf1760..e46ee0d0 100644 | |
| --- a/src/components/po/PurchaseOrderItemCard.tsx | |
| +++ b/src/components/po/PurchaseOrderItemCard.tsx | |
| @@ -458,7 +458,6 @@ export const PurchaseOrderItemCard: React.FC<PurchaseOrderItemCardProps> = ({ | |
| await refetchPurchaseOrder(); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [bulkUpdatePOItems, shownVendors, toast], | |
| ); | |
| @@ -494,7 +493,6 @@ export const PurchaseOrderItemCard: React.FC<PurchaseOrderItemCardProps> = ({ | |
| await refetchPurchaseOrder(); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [bulkUpdatePOItems, shownVendors, toast], | |
| ); | |
| @@ -786,7 +784,6 @@ export const PurchaseOrderItemCard: React.FC<PurchaseOrderItemCardProps> = ({ | |
| ]; | |
| return columns; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| poStatus, | |
| hasManageItemDetailPermission, | |
| diff --git a/src/components/po/useItemSalesBatch.tsx b/src/components/po/useItemSalesBatch.tsx | |
| index f5ec523e..eeecd1ef 100644 | |
| --- a/src/components/po/useItemSalesBatch.tsx | |
| +++ b/src/components/po/useItemSalesBatch.tsx | |
| @@ -107,14 +107,12 @@ export const useItemSalesBatch = ({ | |
| // Get the current requested items | |
| const currentRequestedItems = useMemo(() => { | |
| return Array.from(requestedItems.current); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [queryResults, requestedItems.current]); // Re-compute whenever any query or the set changes | |
| // Return the cached results for the requested items | |
| const data = useMemo(() => { | |
| //trigger a re-render when the loading states change | |
| return { ...cache.current }; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [allLoadingStates]); | |
| return { | |
| diff --git a/src/components/ui/use-toast.ts b/src/components/ui/use-toast.ts | |
| index fc690081..8468d912 100644 | |
| --- a/src/components/ui/use-toast.ts | |
| +++ b/src/components/ui/use-toast.ts | |
| @@ -6,7 +6,7 @@ import type { ToastActionElement, ToastProps } from "@/components/ui/toast"; | |
| const TOAST_LIMIT = 1; | |
| const TOAST_REMOVE_DELAY = 1000000; | |
| -type ToasterToast = Omit<ToastProps, "title"> & { | |
| +type ToasterToast = ToastProps & { | |
| id: string; | |
| title?: React.ReactNode; | |
| description?: React.ReactNode; | |
| @@ -135,25 +135,23 @@ function dispatch(action: Action) { | |
| }); | |
| } | |
| -type Toast = Omit<ToasterToast, "id"> & { | |
| - id?: string; | |
| -}; | |
| +type Toast = Omit<ToasterToast, "id">; | |
| -function toast({ id, ...props }: Toast) { | |
| - const toastId = id || genId(); | |
| +function toast({ ...props }: Toast) { | |
| + const id = genId(); | |
| const update = (props: ToasterToast) => | |
| dispatch({ | |
| type: "UPDATE_TOAST", | |
| - toast: { ...props, id: toastId }, | |
| + toast: { ...props, id }, | |
| }); | |
| - const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId }); | |
| + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); | |
| dispatch({ | |
| type: "ADD_TOAST", | |
| toast: { | |
| ...props, | |
| - id: toastId, | |
| + id, | |
| open: true, | |
| onOpenChange: (open) => { | |
| if (!open) dismiss(); | |
| @@ -162,7 +160,7 @@ function toast({ id, ...props }: Toast) { | |
| }); | |
| return { | |
| - id: toastId, | |
| + id: id, | |
| dismiss, | |
| update, | |
| }; | |
| diff --git a/src/components/ui/wizard.tsx b/src/components/ui/wizard.tsx | |
| deleted file mode 100644 | |
| index 5b499574..00000000 | |
| --- a/src/components/ui/wizard.tsx | |
| +++ /dev/null | |
| @@ -1,253 +0,0 @@ | |
| -import { ArrowLeft, ArrowRight, CheckCircle } from "lucide-react"; | |
| -import React, { ReactNode, useMemo, useState } from "react"; | |
| -import { UseFormReturn } from "react-hook-form"; | |
| -import { cn } from "src/lib/utils"; | |
| -import { Button } from "./button"; | |
| -import { | |
| - Dialog, | |
| - DialogContent, | |
| - DialogDescription, | |
| - DialogFooter, | |
| - DialogHeader, | |
| - DialogTitle, | |
| -} from "./dialog"; | |
| - | |
| -export interface WizardStep { | |
| - title: string; | |
| - description?: string; | |
| - content: ReactNode; | |
| - validation?: () => boolean; | |
| -} | |
| - | |
| -export interface WizardProps { | |
| - steps: WizardStep[]; | |
| - isOpen: boolean; | |
| - onClose: () => void; | |
| - onComplete: (data?: unknown) => void; | |
| - onReset?: () => void; // Callback for form reset | |
| - title?: string; | |
| - description?: string; | |
| - className?: string; | |
| - showStepIndicator?: boolean; | |
| - showStepTitles?: boolean; | |
| - nextButtonText?: string; | |
| - backButtonText?: string; | |
| - completeButtonText?: string; | |
| - cancelButtonText?: string; | |
| - isLoading?: boolean; | |
| - data?: unknown; | |
| - autoResetOnComplete?: boolean; // Whether to automatically reset after completion | |
| - form: UseFormReturn<any>; | |
| -} | |
| - | |
| -export const Wizard: React.FC<WizardProps> = ({ | |
| - steps, | |
| - isOpen, | |
| - onClose, | |
| - onComplete, | |
| - onReset, | |
| - title = "Wizard", | |
| - description = "Complete the steps to proceed", | |
| - className, | |
| - showStepIndicator = true, | |
| - showStepTitles = true, | |
| - nextButtonText = "Next", | |
| - backButtonText = "Back", | |
| - completeButtonText = "Complete", | |
| - cancelButtonText = "Cancel", | |
| - isLoading = false, | |
| - data, | |
| - autoResetOnComplete = true, // Default to true for better UX | |
| - form, | |
| -}) => { | |
| - const [currentStep, setCurrentStep] = useState(0); | |
| - const totalSteps = steps.length; | |
| - | |
| - // Ensure currentStep is within bounds | |
| - const safeCurrentStep = Math.min(Math.max(0, currentStep), totalSteps - 1); | |
| - const currentStepData = steps[safeCurrentStep] ?? { | |
| - validation: () => true, | |
| - content: null, | |
| - }; | |
| - | |
| - const watchedFields = form.watch(); | |
| - const resetWizard = () => { | |
| - setCurrentStep(0); | |
| - onReset?.(); | |
| - }; | |
| - | |
| - const handleNext = async () => { | |
| - // Run validation if provided | |
| - if (currentStepData.validation) { | |
| - try { | |
| - const isValid = await currentStepData.validation(); | |
| - if (!isValid) { | |
| - return; // Don't proceed if validation fails | |
| - } | |
| - } catch (error) { | |
| - console.error("Validation error:", error); | |
| - return; | |
| - } | |
| - } | |
| - | |
| - if (currentStep < totalSteps - 1) { | |
| - setCurrentStep(currentStep + 1); | |
| - } else { | |
| - // Call onComplete with the data | |
| - onComplete(data); | |
| - | |
| - // Automatically reset and close if enabled | |
| - if (autoResetOnComplete) { | |
| - resetWizard(); | |
| - onClose(); | |
| - } | |
| - } | |
| - }; | |
| - | |
| - const handleBack = () => { | |
| - if (currentStep > 0) { | |
| - setCurrentStep(currentStep - 1); | |
| - } | |
| - }; | |
| - | |
| - const handleClose = () => { | |
| - resetWizard(); | |
| - onClose(); | |
| - }; | |
| - | |
| - const canGoToNextStep = useMemo(() => { | |
| - return currentStepData.validation?.() ?? true; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| - }, [currentStepData, watchedFields]); | |
| - | |
| - return ( | |
| - <Dialog open={isOpen} onOpenChange={handleClose}> | |
| - <DialogContent | |
| - className={cn("sm:max-w-3xl max-h-[90vh] overflow-y-auto", className)} | |
| - > | |
| - <DialogHeader> | |
| - <DialogTitle className="flex items-center gap-2"> | |
| - <CheckCircle className="h-5 w-5 text-green-500" /> | |
| - <span>{title}</span> | |
| - <span className="text-sm font-normal text-gray-500"> | |
| - ({safeCurrentStep + 1} of {totalSteps}) | |
| - </span> | |
| - </DialogTitle> | |
| - <DialogDescription>{description}</DialogDescription> | |
| - </DialogHeader> | |
| - | |
| - <div className="space-y-6"> | |
| - {/* Step Progress Indicator */} | |
| - {showStepIndicator && ( | |
| - <div className="flex items-center justify-between"> | |
| - {Array.from({ length: totalSteps }).map((_, index) => ( | |
| - <div | |
| - key={index} | |
| - className={`flex items-center ${ | |
| - index < totalSteps - 1 ? "flex-1" : "" | |
| - }`} | |
| - > | |
| - <div | |
| - className={`flex items-center justify-center w-8 h-8 rounded-full text-sm font-medium ${ | |
| - index <= currentStep | |
| - ? "bg-blue-500 text-white" | |
| - : "bg-gray-100 text-gray-600" | |
| - }`} | |
| - > | |
| - {index + 1} | |
| - </div> | |
| - {showStepTitles && ( | |
| - <span | |
| - className={`ml-2 text-sm font-medium ${ | |
| - index <= currentStep ? "text-blue-500" : "text-gray-500" | |
| - }`} | |
| - > | |
| - {steps[index]?.title} | |
| - </span> | |
| - )} | |
| - {index < totalSteps - 1 && ( | |
| - <div | |
| - className={`flex-1 h-0.5 mx-4 ${ | |
| - index < currentStep ? "bg-blue-500" : "bg-gray-200" | |
| - }`} | |
| - /> | |
| - )} | |
| - </div> | |
| - ))} | |
| - </div> | |
| - )} | |
| - | |
| - {/* Step Content */} | |
| - <div className="min-h-[400px]">{currentStepData.content}</div> | |
| - | |
| - {/* Navigation */} | |
| - <DialogFooter className="gap-2"> | |
| - {currentStep > 0 && ( | |
| - <Button | |
| - type="button" | |
| - variant="outline" | |
| - onClick={handleBack} | |
| - disabled={isLoading} | |
| - > | |
| - <ArrowLeft className="h-4 w-4 mr-2" /> | |
| - {backButtonText} | |
| - </Button> | |
| - )} | |
| - | |
| - <Button | |
| - type="button" | |
| - variant="outline" | |
| - onClick={handleClose} | |
| - disabled={isLoading} | |
| - > | |
| - {cancelButtonText} | |
| - </Button> | |
| - | |
| - <Button | |
| - type="button" | |
| - onClick={handleNext} | |
| - disabled={!canGoToNextStep || isLoading} | |
| - isLoading={isLoading} | |
| - > | |
| - {currentStep === totalSteps - 1 | |
| - ? completeButtonText | |
| - : nextButtonText} | |
| - {currentStep < totalSteps - 1 && ( | |
| - <ArrowRight className="h-4 w-4 ml-2" /> | |
| - )} | |
| - </Button> | |
| - </DialogFooter> | |
| - </div> | |
| - </DialogContent> | |
| - </Dialog> | |
| - ); | |
| -}; | |
| - | |
| -// Hook for managing wizard state | |
| -export const useWizard = (steps: WizardStep[]) => { | |
| - const [isOpen, setIsOpen] = useState(false); | |
| - const [data, setData] = useState<unknown>(null); | |
| - | |
| - const openWizard = (initialData?: unknown) => { | |
| - setData(initialData); | |
| - setIsOpen(true); | |
| - }; | |
| - | |
| - const closeWizard = () => { | |
| - setIsOpen(false); | |
| - setData(null); | |
| - }; | |
| - | |
| - const completeWizard = (finalData?: unknown) => { | |
| - // You can add completion logic here | |
| - closeWizard(); | |
| - }; | |
| - | |
| - return { | |
| - isOpen, | |
| - openWizard, | |
| - closeWizard, | |
| - completeWizard, | |
| - data, | |
| - }; | |
| -}; | |
| diff --git a/src/config/phoenix-client.ts b/src/config/phoenix-client.ts | |
| deleted file mode 100644 | |
| index 466d25d9..00000000 | |
| --- a/src/config/phoenix-client.ts | |
| +++ /dev/null | |
| @@ -1,145 +0,0 @@ | |
| -import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios"; | |
| -import qs from "qs"; | |
| -import { RegisterType } from "src/context/RegisterProvider"; | |
| -import { typeid } from "typeid-js"; | |
| -import { firebaseAuth } from "./Firebase/firebase"; | |
| - | |
| -export const REQUEST_HEADER_KEY = "X-Request-ID"; | |
| - | |
| -export type RequestConfig<TData = unknown> = { | |
| - url?: string; | |
| - method: "get" | "put" | "patch" | "post" | "delete"; | |
| - params?: unknown; | |
| - data?: TData; | |
| - responseType?: | |
| - | "arraybuffer" | |
| - | "blob" | |
| - | "document" | |
| - | "json" | |
| - | "text" | |
| - | "stream"; | |
| - baseURL?: string; | |
| - signal?: AbortSignal; | |
| - headers?: AxiosRequestConfig["headers"]; | |
| - adapter?: AxiosRequestConfig["adapter"]; | |
| -}; | |
| -/** | |
| - * Subset of AxiosResponse | |
| - */ | |
| -export type ResponseConfig<TData = unknown> = { | |
| - data: TData; | |
| - status: number; | |
| - statusText: string; | |
| - headers?: AxiosResponse["headers"]; | |
| -}; | |
| - | |
| -export const CORE_POS_PATHS = new Set( | |
| - ["/sale", "/signin", "/register/open"].map((s) => s.replace(/\/$/, "")), | |
| -); | |
| - | |
| -export function REDIRECT_TO_CORE_SALE_API() { | |
| - const pathname = window.location.pathname; | |
| - // remove trailing slash if exists | |
| - const path = pathname.replace(/\/$/, ""); | |
| - | |
| - if (CORE_POS_PATHS.has(path)) { | |
| - return "CRITICAL"; | |
| - } | |
| - return "STABLE"; | |
| -} | |
| - | |
| -// Global variable to store current entity ID for axios interceptor | |
| -export let currentEntityId: number | undefined; | |
| - | |
| -// Function to update the entity ID from React context | |
| -export const setCurrentEntityId = (entityId: number | undefined) => { | |
| - currentEntityId = entityId; | |
| -}; | |
| - | |
| -export const client = axios.create({ | |
| - baseURL: import.meta.env.VITE_APP_PHOENIX_URL, | |
| - paramsSerializer: (params) => qs.stringify(params, { indices: false }), | |
| -}); | |
| -client.interceptors.request.use(async (config) => { | |
| - const currentUser = firebaseAuth.currentUser; | |
| - | |
| - config.headers["X-AVAILABILITY"] = REDIRECT_TO_CORE_SALE_API(); | |
| - const token = await currentUser?.getIdToken(); | |
| - if (token) { | |
| - config.headers.Authorization = `Bearer ${token}`; | |
| - config.headers["X-User-ID"] = currentUser?.uid; | |
| - } | |
| - return config; | |
| -}); | |
| - | |
| -// https://github.com/kubb-labs/kubb/commit/87370f5b09df4429e4ee8e3d40494e66f36c9484 | |
| -// kubb overrides the baseURL with the first server in the servers array | |
| -client.interceptors.request.use((config) => { | |
| - config.baseURL = import.meta.env.VITE_APP_PHOENIX_URL; | |
| - return config; | |
| -}); | |
| - | |
| -client.interceptors.request.use((config) => { | |
| - // Set X-Entity-ID header using the global entity ID | |
| - if (!config.headers.has("X-Entity-ID") && currentEntityId) { | |
| - config.headers["X-Entity-ID"] = currentEntityId; | |
| - } | |
| - | |
| - const entityId = config.headers["X-Entity-ID"]; | |
| - if (entityId) { | |
| - const registerJson = JSON.parse( | |
| - // @ts-ignore null can be passed into JSON.parse | |
| - localStorage.getItem(`${entityId}-registerOpen`), | |
| - ) as RegisterType | null; | |
| - | |
| - if (registerJson && registerJson.isRegisterOpen) { | |
| - config.headers["X-Register-ID"] = registerJson.registerNumber; | |
| - } | |
| - } | |
| - | |
| - return config; | |
| -}); | |
| - | |
| -client.interceptors.request.use((config) => { | |
| - if (config.url && config.url.includes("items/export")) { | |
| - config.url = config.url.replace("items/export", "items/exports"); | |
| - } | |
| - return config; | |
| -}); | |
| -client.interceptors.request.use((config) => { | |
| - if (config.headers.has(REQUEST_HEADER_KEY)) { | |
| - return config; | |
| - } | |
| - config.headers[REQUEST_HEADER_KEY] = typeid("req").toString(); | |
| - console.log(config.headers[REQUEST_HEADER_KEY], config.url); | |
| - config.params = { | |
| - ...config.params, | |
| - request_id: config.headers[REQUEST_HEADER_KEY], | |
| - }; | |
| - return config; | |
| -}); | |
| - | |
| -// Send timezone id as a header | |
| -client.interceptors.request.use((config) => { | |
| - const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; | |
| - config.headers["X-Timezone"] = timezone; | |
| - return config; | |
| -}); | |
| - | |
| -export const axiosClient = async < | |
| - TData, | |
| - TError = unknown, | |
| - TVariables = unknown, | |
| ->( | |
| - config: RequestConfig<TVariables>, | |
| -): Promise<AxiosResponse<TData>> => { | |
| - const promise = client | |
| - .request<TData>({ ...config }) | |
| - .catch((e: AxiosError<TError>) => { | |
| - throw e; | |
| - }); | |
| - | |
| - return promise; | |
| -}; | |
| - | |
| -export default axiosClient; | |
| diff --git a/src/context/AppVersionContext.tsx b/src/context/AppVersionContext.tsx | |
| index eb81ab19..cdac5126 100644 | |
| --- a/src/context/AppVersionContext.tsx | |
| +++ b/src/context/AppVersionContext.tsx | |
| @@ -11,57 +11,27 @@ import { | |
| } from "react"; | |
| import { toast } from "sonner"; | |
| import { useInterval, useLocalStorage } from "usehooks-ts"; | |
| -import { | |
| - ORIGIN_DOMAIN_HEADER, | |
| - SERVED_FROM_HEADER, | |
| - STACK_NAME_HEADER, | |
| -} from "utils/constants"; | |
| - | |
| -interface VersionInfo { | |
| - version: string; | |
| - originDomain?: string; | |
| - stackName?: string; | |
| - servedFrom?: string; | |
| -} | |
| export const AppVersionContext = createContext< | |
| | { | |
| currentVersion: string; | |
| showingUpdatePrompt: boolean; | |
| - originDomain?: string; | |
| - stackName?: string; | |
| - servedFrom?: string; | |
| } | |
| | undefined | |
| >(undefined); | |
| const UPDATE_INTERVAL_MS = 1000 * 60 * 10; // Check for updates every minute | |
| const VERSION_URL = "/version.json"; | |
| -const getNewVersion: () => Promise<VersionInfo> = async () => { | |
| +const getNewVersion: () => Promise<string> = async () => { | |
| try { | |
| console.log("Checking version"); | |
| const response = await fetch(VERSION_URL, { cache: "no-store" }); | |
| const version = await response.json(); | |
| - const headers = response.headers; | |
| - const originDomain = headers.get(ORIGIN_DOMAIN_HEADER); | |
| - const stackName = headers.get(STACK_NAME_HEADER); | |
| - const servedFrom = headers.get(SERVED_FROM_HEADER); | |
| - | |
| - return { | |
| - version: version.version, | |
| - originDomain: originDomain ?? undefined, | |
| - stackName: stackName ?? undefined, | |
| - servedFrom: servedFrom ?? undefined, | |
| - }; | |
| + return version.version; | |
| } catch (error) { | |
| console.warn("Error checking version: ", error); | |
| - return { | |
| - version: "", | |
| - originDomain: undefined, | |
| - stackName: undefined, | |
| - servedFrom: undefined, | |
| - }; | |
| + return ""; | |
| } | |
| }; | |
| @@ -71,14 +41,9 @@ export const AppVersionProvider = ({ | |
| children: React.ReactNode; | |
| }) => { | |
| const isFirstRender = useIsFirstRender(); | |
| - const [currentVersion, setCurrentVersion] = useLocalStorage<VersionInfo>( | |
| - "currentVersion-09-17-25", | |
| - { | |
| - version: "", | |
| - originDomain: undefined, | |
| - stackName: undefined, | |
| - servedFrom: undefined, | |
| - }, | |
| + const [currentVersion, setCurrentVersion] = useLocalStorage<string>( | |
| + "currentVersion-11-19-24", | |
| + "", | |
| ); | |
| // for some reason requires string | number | |
| const [toastId, setToastId] = useState<string | number | undefined>( | |
| @@ -86,7 +51,7 @@ export const AppVersionProvider = ({ | |
| ); | |
| const displayUpdatePrompt = useCallback( | |
| - (newVersion: VersionInfo) => { | |
| + (newVersion: string) => { | |
| if (toastId) { | |
| toast.dismiss(toastId); | |
| } | |
| @@ -129,7 +94,7 @@ export const AppVersionProvider = ({ | |
| setCurrentVersion(newVersion); | |
| return; | |
| } | |
| - if (newVersion.version !== currentVersion.version) { | |
| + if (newVersion !== currentVersion) { | |
| displayUpdatePrompt(newVersion); | |
| } | |
| }, [currentVersion, displayUpdatePrompt, setCurrentVersion]); | |
| @@ -150,11 +115,8 @@ export const AppVersionProvider = ({ | |
| return ( | |
| <AppVersionContext.Provider | |
| value={{ | |
| - currentVersion: currentVersion.version, | |
| + currentVersion, | |
| showingUpdatePrompt: useMemo(() => toastId !== undefined, [toastId]), | |
| - originDomain: currentVersion.originDomain, | |
| - stackName: currentVersion.stackName, | |
| - servedFrom: currentVersion.servedFrom, | |
| }} | |
| > | |
| {children} | |
| diff --git a/src/context/AuthenticationContext/AuthenticationContext.tsx b/src/context/AuthenticationContext/AuthenticationContext.tsx | |
| index a4854997..c9ec0748 100644 | |
| --- a/src/context/AuthenticationContext/AuthenticationContext.tsx | |
| +++ b/src/context/AuthenticationContext/AuthenticationContext.tsx | |
| @@ -1,4 +1,3 @@ | |
| -import { useStatsigClient } from "@statsig/react-bindings"; | |
| import { | |
| firebaseAuth, | |
| firebaseAuthOverridden, | |
| @@ -70,7 +69,6 @@ export const AuthContextProvider = ({ | |
| }: AuthContextProviderProps) => { | |
| const [isLoading, setIsLoading] = useState(true); | |
| const posthog = usePostHog(); | |
| - const { client: statsigClient } = useStatsigClient(); | |
| const [user, setUser] = useFirebaseSyncedUser( | |
| firebaseAuth, | |
| useCallback(() => setIsLoading(false), []), | |
| @@ -195,7 +193,6 @@ export const AuthContextProvider = ({ | |
| if (!user?.uid) { | |
| posthog.reset(); | |
| Sentry.setUser(null); | |
| - statsigClient.updateUserSync({ userID: undefined }); | |
| setAuthenticated(false); | |
| return; | |
| } | |
| @@ -219,17 +216,11 @@ export const AuthContextProvider = ({ | |
| ip_address: "{{auto}}", | |
| }); | |
| - statsigClient.updateUserSync({ | |
| - userID: user.uid, | |
| - email: user.email ?? undefined, | |
| - }); | |
| - | |
| window.Atlas.call("identify", { | |
| userId: user.uid, | |
| name: user.displayName, | |
| email: user.email, | |
| }); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [posthog, setAuthenticated, user?.displayName, user?.email, user?.uid]); | |
| useEffect(() => { | |
| diff --git a/src/context/DepartmentContext.tsx b/src/context/DepartmentContext.tsx | |
| index 7a4f5d24..84a62020 100644 | |
| --- a/src/context/DepartmentContext.tsx | |
| +++ b/src/context/DepartmentContext.tsx | |
| @@ -100,8 +100,8 @@ export const DepartmentProvider = ({ children }: { children: ReactNode }) => { | |
| // need to find a better way to do this, maybe register callbacks on entity changes in EntityProvider | |
| useEffect(() => { | |
| refetch(); | |
| - // causes infinite re-render, only want to run on cohortId change | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| + // causes infinite re-render, only want to run on cohortId change | |
| }, [cohortId]); | |
| const value = useMemo( | |
| diff --git a/src/context/EntityProvider.tsx b/src/context/EntityProvider.tsx | |
| index 7830ce03..cc3e03ea 100644 | |
| --- a/src/context/EntityProvider.tsx | |
| +++ b/src/context/EntityProvider.tsx | |
| @@ -1,6 +1,5 @@ | |
| -import { useStatsigClient } from "@statsig/react-bindings"; | |
| import { useQueryClient } from "@tanstack/react-query"; | |
| -import { captureException, setTag } from "config/sentry/TransformitySentry"; | |
| +import { setTag } from "config/sentry/TransformitySentry"; | |
| import { usePostHog } from "posthog-js/react"; | |
| import { | |
| createContext, | |
| @@ -142,7 +141,6 @@ export const EntityContextProvider = ({ | |
| ); | |
| const [entity, setEntity] = useState<EntityDto>(); | |
| const posthog = usePostHog(); | |
| - const { client: statsigClient } = useStatsigClient(); | |
| const queryClient = useQueryClient(); | |
| const entityRetrieve = useCallback( | |
| @@ -218,28 +216,8 @@ export const EntityContextProvider = ({ | |
| name: entity.cohortId, | |
| id: entity.cohortId, | |
| }); | |
| - | |
| - try { | |
| - const updatedUser = { | |
| - ...statsigClient.getContext().user, | |
| - customIDs: { | |
| - entityId: entity.id.toString(), | |
| - cohortId: entity.cohortId.toString(), | |
| - }, | |
| - }; | |
| - statsigClient.dataAdapter | |
| - .prefetchData(updatedUser) | |
| - .then(() => { | |
| - statsigClient.updateUserSync(updatedUser); | |
| - }) | |
| - .catch((error) => { | |
| - captureException(error); | |
| - }); | |
| - } catch (error) { | |
| - captureException(error); | |
| - } | |
| } | |
| - }, [entity, posthog, statsigClient]); | |
| + }, [entity, posthog]); | |
| useEffect(() => { | |
| if (entity && user) { | |
| diff --git a/src/context/InvoiceContext.tsx b/src/context/InvoiceContext.tsx | |
| index e384107b..8009cef6 100644 | |
| --- a/src/context/InvoiceContext.tsx | |
| +++ b/src/context/InvoiceContext.tsx | |
| @@ -255,7 +255,6 @@ export const InvoiceProvider: React.FC<InvoiceProviderProps> = ({ | |
| invoice.invoiceItems[itemIndex] = item; | |
| setInvoice(structuredClone(invoice)); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [invoice, postInvoiceItem], | |
| ); | |
| diff --git a/src/context/Sales/SalesContext.tsx b/src/context/Sales/SalesContext.tsx | |
| index e6e83632..bdee7490 100644 | |
| --- a/src/context/Sales/SalesContext.tsx | |
| +++ b/src/context/Sales/SalesContext.tsx | |
| @@ -1,4 +1,3 @@ | |
| -import { RetrieveItemsByUpc } from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { GovernmentID } from "model/data-contracts"; | |
| import { LineItem } from "pages/SalePage/SalePageUtils"; | |
| import { createContext, useContext } from "react"; | |
| @@ -8,11 +7,10 @@ import { | |
| DraftTransactionInput, | |
| DraftTransactionItemInput, | |
| DraftTransactionMutationResponse, | |
| + EntityItemDetail, | |
| LoyaltyCustomer, | |
| TransactionId, | |
| - TransactionPaymentForm, | |
| } from "src/generated"; | |
| -import { EntitySalesChannelPaymentMethod } from "src/spring-generated"; | |
| import { SalesPaymentContextType } from "./SalesPaymentContext"; | |
| export type DraftTransactionArgs = Partial< | |
| @@ -24,9 +22,6 @@ export type PricingRequestOptions = { | |
| requestedDiscount?: Discount; | |
| requestTaxExempt: boolean; | |
| requestedCustomer?: LoyaltyCustomer; | |
| - paymentMethodId?: string; | |
| - overriddenPriceLevel?: number; | |
| - hasOverriddenPriceLevel?: boolean; | |
| }; | |
| export interface SalesContextType { | |
| @@ -42,7 +37,7 @@ export interface SalesContextType { | |
| >; | |
| addSingleItemToCart: ( | |
| itemDetailz: | |
| - | RetrieveItemsByUpc | |
| + | EntityItemDetail | |
| | Omit<DraftTransactionItemInput, "transactionId">, | |
| quantity: number, | |
| ) => void; | |
| @@ -58,14 +53,11 @@ export interface SalesContextType { | |
| id: SalesContextType["governmentID"], | |
| ) => void | Promise<void>; | |
| customer?: LoyaltyCustomer; | |
| - transactionTotalPrice: (options?: { | |
| - items?: SalesContextType["items"]; | |
| - paymentMethodId?: string; | |
| - }) => number; | |
| + transactionTotalPrice: (itemz?: SalesContextType["items"]) => number; | |
| clearCart: () => Promise<void>; | |
| - resetCartToCurrentItems: () => Promise<void>; | |
| + resetCartToCurrentItems: () => void; | |
| handleRetrievedItems: ( | |
| - items: RetrieveItemsByUpc[], | |
| + items: EntityItemDetail[], | |
| quantity: number, | |
| ) => Promise<void>; | |
| retrieveItemsLikeUpc: ( | |
| @@ -73,17 +65,14 @@ export interface SalesContextType { | |
| exact?: boolean, | |
| quantity?: number, | |
| ) => void; | |
| - multipleChoices: | |
| - | { items: RetrieveItemsByUpc[]; quantity: number } | |
| - | undefined; | |
| + multipleChoices: { items: EntityItemDetail[]; quantity: number } | undefined; | |
| setMultipleChoices: React.Dispatch< | |
| React.SetStateAction< | |
| - { items: RetrieveItemsByUpc[]; quantity: number } | undefined | |
| + { items: EntityItemDetail[]; quantity: number } | undefined | |
| > | |
| >; | |
| deviceBusy: boolean; | |
| setDeviceBusy: React.Dispatch<React.SetStateAction<boolean>>; | |
| - isCalculatingBackgroundPaymentMethodTotals: boolean; | |
| transactionId?: number; | |
| setTransactionId: ( | |
| transactionId?: TransactionId, | |
| @@ -94,19 +83,6 @@ export interface SalesContextType { | |
| isCalculatingCartPrice: boolean; | |
| isGetCartPricingError: boolean; | |
| setItemsInCart: (items: Map<number, LineItem>) => Promise<void>; | |
| - paymentMethodTypeToPaymentMethod: Record< | |
| - string, | |
| - Array<EntitySalesChannelPaymentMethod> | |
| - >; | |
| - hasMultiplePriceLevelsOnSalesChannel: boolean; | |
| - calculateMethodsWithPrices: ( | |
| - paymentForm: TransactionPaymentForm, | |
| - ) => Array<{ method: EntitySalesChannelPaymentMethod; total: number }>; | |
| - findBestPaymentMethod: ( | |
| - paymentMethods: EntitySalesChannelPaymentMethod[] | undefined, | |
| - defaultPaymentMethodId?: string, | |
| - ) => EntitySalesChannelPaymentMethod | null; | |
| - setSkipSetItemsInCart: (skip: boolean) => void; | |
| } | |
| export const SalesContext = createContext<SalesContextType | undefined>( | |
| @@ -119,7 +95,7 @@ export const getTotalQuantity = ( | |
| return [...items.values()].reduce( | |
| (partialSum, a) => | |
| // DEPOSIT should not count against total quantity | |
| - partialSum + (!a.item?.dp_has_revenue ? 0 : a.quantity), | |
| + partialSum + (!a.item?.cohortItem.department.hasRevenue ? 0 : a.quantity), | |
| 0, | |
| ); | |
| }; | |
| diff --git a/src/context/Sales/SalesContextProvider.tsx b/src/context/Sales/SalesContextProvider.tsx | |
| index 2de10f70..6db69bf3 100644 | |
| --- a/src/context/Sales/SalesContextProvider.tsx | |
| +++ b/src/context/Sales/SalesContextProvider.tsx | |
| @@ -1,12 +1,7 @@ | |
| import { useToast } from "@chakra-ui/react"; | |
| -import { usePGlite } from "@electric-sql/pglite-react"; | |
| import { useQueryClient } from "@tanstack/react-query"; | |
| import { useDebounce } from "@uidotdev/usehooks"; | |
| import { CanceledError, isAxiosError } from "axios"; | |
| -import { | |
| - type RetrieveItemsByUpc, | |
| - RetrieveItemsByUpcQuery, | |
| -} from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { useSalePageConfig } from "components/SalesScreenComponents/SalePageConfigProvider"; | |
| import { | |
| captureException, | |
| @@ -14,38 +9,34 @@ import { | |
| } from "config/sentry/TransformitySentry"; | |
| import { isEqual, round } from "lodash-es"; | |
| import posthog from "posthog-js"; | |
| -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; | |
| +import { useCallback, useEffect, useRef, useState } from "react"; | |
| import { Navigate, useBeforeUnload, useBlocker } from "react-router-dom"; | |
| import { | |
| CartDiscountType, | |
| - type Discount, | |
| - type DraftTransactionInput, | |
| - type DraftTransactionItemInput, | |
| + Discount, | |
| + DraftTransactionInput, | |
| + DraftTransactionItemInput, | |
| + EntityItemDetail, | |
| getCartPricing as getCartPricingRequest, | |
| getItemByIdQueryOptions, | |
| getLoyaltyCustomerQueryOptions, | |
| getTransactionByIdQueryOptions, | |
| - type GovernmentId, | |
| - type LoyaltyCustomer, | |
| - type PricingCartInputItem, | |
| + GovernmentId, | |
| + LoyaltyCustomer, | |
| + PricingCartInputItem, | |
| PricingCartInputItemType, | |
| - type PricingCartOutputItem, | |
| + PricingCartOutputItem, | |
| retrieveItemsLikeUpcQueryOptions, | |
| - type TransactionCartItem, | |
| - type TransactionId, | |
| - TransactionPaymentForm, | |
| - type UnknownItem, | |
| + TransactionCartItem, | |
| + TransactionId, | |
| + UnknownItem, | |
| useDraftTransaction, | |
| useDraftTransactionItem, | |
| useEmptyCart, | |
| useSetItemsInCart, | |
| } from "src/generated"; | |
| import { useGetAllDepartmentsForEntity } from "src/hooks/useGetAllDepartmentsForEntity"; | |
| -import { | |
| - EntitySalesChannelPaymentMethod, | |
| - useCreateTransactionHold, | |
| - useSearchEntitySalesChannelPaymentMethods, | |
| -} from "src/spring-generated"; | |
| +import { useCreateTransactionHold } from "src/spring-generated"; | |
| import { useLocalStorage } from "usehooks-ts"; | |
| import Loading from "../../components/Loading"; | |
| import { | |
| @@ -53,7 +44,7 @@ import { | |
| convertToPricingCartInputItem, | |
| getDiscountMap, | |
| hasCalculationWarning, | |
| - type LineItem, | |
| + LineItem, | |
| } from "../../pages/SalePage/SalePageUtils"; | |
| import { playFailureSound } from "../../utils/audioUtils"; | |
| import { | |
| @@ -62,10 +53,9 @@ import { | |
| } from "../EntityProvider"; | |
| import { useRegisterProvider } from "../RegisterProvider"; | |
| import { | |
| - type DraftTransactionArgs, | |
| - type PricingRequestOptions, | |
| + DraftTransactionArgs, | |
| + PricingRequestOptions, | |
| SalesContext, | |
| - SalesContextType, | |
| } from "./SalesContext"; | |
| export interface SalesContextProviderProps { | |
| @@ -108,64 +98,9 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| const { id: programId } = useLoyaltyProgramIdOptional(); | |
| const [entity, , isEntityLoading] = useEntitySelected(); | |
| const toast = useToast(); | |
| - | |
| const { departmentMap, departmentKeyMap } = useGetAllDepartmentsForEntity(); | |
| - const { | |
| - selectedSalesChannel, | |
| - selectSalesChannel, | |
| - resetSalesChannel, | |
| - overriddenCohortPriceLevel, | |
| - selectOverriddenCohortPriceLevel, | |
| - resetOverriddenCohortPriceLevel, | |
| - } = useSalePageConfig(); | |
| - | |
| - // Get payment methods for the current sales channel | |
| - const { data: paymentMethods } = useSearchEntitySalesChannelPaymentMethods( | |
| - { | |
| - entitySalesChannelId: selectedSalesChannel?.id, | |
| - entityId: entity.id, | |
| - isArchived: false, | |
| - }, | |
| - { | |
| - query: { | |
| - enabled: | |
| - !!selectedSalesChannel?.id && | |
| - !!entity.id && | |
| - selectedSalesChannel.entityId === entity.id, | |
| - }, | |
| - }, | |
| - ); | |
| - | |
| - const paymentMethodTypeToPaymentMethod = useMemo(() => { | |
| - return ( | |
| - paymentMethods?.content?.reduce( | |
| - (acc, paymentMethod) => { | |
| - const paymentForm = paymentMethod.paymentMethodType.replace( | |
| - "_", | |
| - " ", | |
| - ) as TransactionPaymentForm; | |
| - | |
| - if (!acc[paymentForm]) { | |
| - acc[paymentForm] = []; | |
| - } | |
| - acc[paymentForm].push(paymentMethod); | |
| - return acc; | |
| - }, | |
| - {} as Record< | |
| - TransactionPaymentForm, | |
| - Array<EntitySalesChannelPaymentMethod> | |
| - >, | |
| - ) ?? | |
| - ({} as Record< | |
| - TransactionPaymentForm, | |
| - Array<EntitySalesChannelPaymentMethod> | |
| - >) | |
| - ); | |
| - }, [paymentMethods]); | |
| - | |
| - // Track the override payment method (defaults to sales channel default, can be overridden) | |
| - // Now managed by the store via useSalePageConfig | |
| - | |
| + const { selectedSalesChannel, selectSalesChannel, resetSalesChannel } = | |
| + useSalePageConfig(); | |
| const [isTransactionLoading, setTransactionLoading] = useState(true); | |
| const [transactionId, setTransactionId] = useLocalStorage< | |
| TransactionId | undefined | |
| @@ -216,7 +151,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| const [items, setItems] = useState<itemT>(); | |
| const queryClient = useQueryClient(); | |
| - const db = usePGlite(); | |
| const itemsUndefined = items === undefined; | |
| const { register } = useRegisterProvider(); | |
| @@ -252,13 +186,11 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| if (inputtedTransactionId) { | |
| setTransactionId(inputtedTransactionId); | |
| } | |
| - resetOverriddenCohortPriceLevel(); | |
| - setPaymentMethodIdToCartTotal({}); | |
| return await draftTransaction({ | |
| id: inputtedTransactionId, | |
| }); | |
| }, | |
| - [draftTransaction, setTransactionId, resetOverriddenCohortPriceLevel], | |
| + [draftTransaction, setTransactionId], | |
| ); | |
| useEffect(() => { | |
| @@ -277,27 +209,19 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| .fetchQuery(getTransactionOptions) | |
| .then(async (res) => { | |
| for (const transactionItem of res.transactionItems) { | |
| - const entityItemOptions = transactionItem.itemId | |
| + const entityItemOptions = !!transactionItem.itemId | |
| ? getItemByIdQueryOptions(transactionItem.itemId) | |
| : undefined; | |
| - const entityItem = entityItemOptions | |
| + const entityItem = !!entityItemOptions | |
| ? await queryClient.fetchQuery(entityItemOptions) | |
| : undefined; | |
| - const options = RetrieveItemsByUpcQuery( | |
| - entity.id, | |
| - null, | |
| - entityItem?.id ? [entityItem.id] : [], | |
| - ); | |
| - const eRes = entityItem?.id | |
| - ? await db.query<RetrieveItemsByUpc>(options.query, options.params) | |
| - : undefined; | |
| newItemDetails.set(transactionItem.id, { | |
| ...transactionItem, | |
| tax: transactionItem.tax, | |
| taxRate: transactionItem.taxRate ?? 0, | |
| promotionItems: transactionItem.promotionItems, | |
| discount: transactionItem.discount ?? 0, | |
| - item: eRes?.rows?.[0], | |
| + item: entityItem, | |
| itemId: transactionItem.itemId, | |
| transactionId: transactionId, | |
| department: transactionItem.department ?? 0, | |
| @@ -313,7 +237,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| } | |
| : undefined, | |
| ); | |
| - | |
| const transactionCustomerId = res.customerId; | |
| let customerRes: LoyaltyCustomer | undefined; | |
| if (!!transactionCustomerId && programId !== undefined) { | |
| @@ -328,7 +251,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| resetSalesChannel(); | |
| } else if (res.salesChannelId !== selectedSalesChannel.id) { | |
| void selectSalesChannel(res.salesChannelId); | |
| - | |
| const lineItemDiscount = customerRes?.lineItemFixedDiscount; | |
| const lineItemDiscountPercent = lineItemDiscount | |
| ? lineItemDiscount * 100 | |
| @@ -341,19 +263,18 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| } | |
| : undefined; | |
| } | |
| + await calculateCartPriceRef | |
| + .current({ | |
| + requestedItems: newItemDetails, | |
| + requestedCustomer: customerRes, | |
| + requestTaxExempt: res.taxExempt ?? false, | |
| + requestedDiscount: !customerRes?.lineItemFixedDiscount | |
| + ? customerDiscount(customerRes) | |
| + : undefined, | |
| + }) | |
| + // no need to do anything. handled in calculateCartPrice | |
| + .finally(() => undefined); | |
| } | |
| - await calculateCartPriceRef | |
| - .current({ | |
| - requestedItems: newItemDetails, | |
| - requestedCustomer: customerRes, | |
| - requestTaxExempt: res.taxExempt ?? false, | |
| - requestedDiscount: !customerRes?.lineItemFixedDiscount | |
| - ? customerDiscount(customerRes) | |
| - : undefined, | |
| - }) | |
| - .catch((err) => { | |
| - return Promise.resolve(); | |
| - }); | |
| }) | |
| .catch(async (err) => { | |
| toast({ | |
| @@ -379,12 +300,9 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| setOrResetTransactionId, | |
| register.isRegisterOpen, | |
| selectedSalesChannel.id, | |
| - selectOverriddenCohortPriceLevel, | |
| selectSalesChannel, | |
| resetSalesChannel, | |
| programId, | |
| - entity.id, | |
| - db, | |
| ]); | |
| // State | |
| @@ -400,7 +318,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| Map<number, Discount> | |
| >(getDiscountMap(items ?? new Map())); | |
| const [multipleChoices, setMultipleChoices] = useState<{ | |
| - items: RetrieveItemsByUpc[]; | |
| + items: EntityItemDetail[]; | |
| quantity: number; | |
| }>(); | |
| const [deviceBusy, setDeviceBusy] = useState(false); | |
| @@ -415,16 +333,9 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| ); | |
| const cartDisplayAbortController = useRef<AbortController | null>(null); | |
| const cartPricingAbortController = useRef<AbortController | null>(null); | |
| - const backgroundCalculationAbortController = useRef<AbortController | null>( | |
| - null, | |
| - ); | |
| + const debouncedItems = useDebounce(items, 650); | |
| const [isGetCartPricingError, setIsGetCartPricingError] = useState(false); | |
| const cartPriceCallInProgress = useRef(false); | |
| - const skipSetItemsInCartRef = useRef(false); | |
| - | |
| - const setSkipSetItemsInCart = useCallback((skip: boolean) => { | |
| - skipSetItemsInCartRef.current = skip; | |
| - }, []); | |
| const { mutateAsync: setItemsInCartMutate } = useSetItemsInCart({ | |
| mutation: { | |
| @@ -450,19 +361,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| [], | |
| ); | |
| - const [paymentMethodIdToCartTotal, setPaymentMethodIdToCartTotal] = useState< | |
| - Record<string, number> | |
| - >({}); | |
| - | |
| - const [debouncedItems, debouncedTotals] = useDebounce< | |
| - [Map<number, LineItem> | undefined, Record<string, number> | undefined] | |
| - >([items, paymentMethodIdToCartTotal], 650); | |
| - | |
| - const [ | |
| - isCalculatingBackgroundPaymentMethodTotals, | |
| - setIsCalculatingBackgroundPaymentMethodTotals, | |
| - ] = useState(false); | |
| - | |
| const { mutateAsync: createTransactionHold } = useCreateTransactionHold({ | |
| mutation: { | |
| onError(e) { | |
| @@ -473,14 +371,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| const migrationInProgressRef = useRef(false); | |
| - const hasMultiplePriceLevelsOnSalesChannel = useMemo(() => { | |
| - return ( | |
| - new Set( | |
| - (paymentMethods?.content || []).map((pm) => pm.cohortPriceLevelId), | |
| - ).size > 1 | |
| - ); | |
| - }, [paymentMethods]); | |
| - | |
| useEffect(() => { | |
| const migrateCarts = async () => { | |
| // Prevent concurrent migrations | |
| @@ -520,6 +410,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| extra: { cart, migrationStep: "createTransactionHold" }, | |
| }); | |
| remainingCarts.push(cart); | |
| + continue; | |
| } | |
| } | |
| @@ -545,21 +436,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| // Callbacks | |
| const transactionTotalPrice = useCallback( | |
| - (options?: { | |
| - items?: SalesContextType["items"]; | |
| - paymentMethodId?: string; | |
| - }): number => { | |
| - const { items: itemz = items, paymentMethodId } = options || {}; | |
| - | |
| - if (paymentMethodId && paymentMethods?.content) { | |
| - // Find the payment method ID that matches the requested payment method form | |
| - if (overriddenCohortPriceLevel === undefined) { | |
| - return ( | |
| - paymentMethodIdToCartTotal[paymentMethodId] ?? | |
| - transactionTotalPrice() | |
| - ); | |
| - } | |
| - } | |
| + (itemz = items) => { | |
| if (!itemz) return 0; | |
| let price = 0; | |
| for (const [, lineItem] of itemz) { | |
| @@ -567,55 +444,12 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| } | |
| return round(price, 2); | |
| }, | |
| - [ | |
| - items, | |
| - paymentMethodIdToCartTotal, | |
| - paymentMethods?.content, | |
| - overriddenCohortPriceLevel, | |
| - ], | |
| - ); | |
| - | |
| - // Helper function to find the best payment method (default if available, otherwise cheapest) | |
| - const findBestPaymentMethod = useCallback( | |
| - ( | |
| - paymentMethods: EntitySalesChannelPaymentMethod[] | undefined, | |
| - defaultPaymentMethodId?: string, | |
| - ) => { | |
| - if (!paymentMethods || paymentMethods.length === 0) return null; | |
| - | |
| - // First, try to find the default payment method | |
| - const defaultMethod = paymentMethods.find( | |
| - (pm) => pm.id === defaultPaymentMethodId, | |
| - ); | |
| - if (defaultMethod) { | |
| - return defaultMethod; | |
| - } | |
| - | |
| - // If no default found, find the cheapest one | |
| - let cheapestMethod = paymentMethods[0]; | |
| - let cheapestPrice = transactionTotalPrice({ | |
| - paymentMethodId: cheapestMethod?.id, | |
| - }); | |
| - | |
| - for (const method of paymentMethods) { | |
| - const price = transactionTotalPrice({ paymentMethodId: method.id }); | |
| - if (price < cheapestPrice) { | |
| - cheapestPrice = price; | |
| - cheapestMethod = method; | |
| - } | |
| - } | |
| - | |
| - return cheapestMethod || null; | |
| - }, | |
| - [transactionTotalPrice], | |
| + [items], | |
| ); | |
| const setItemsInCart = useCallback( | |
| - async ( | |
| - it: Map<number, LineItem>, | |
| - paymentMethodIdToCartTotal: Record<string, number> = {}, | |
| - ) => { | |
| - if (!register.isRegisterOpen || skipSetItemsInCartRef.current) return; | |
| + async (it: Map<number, LineItem>) => { | |
| + if (!register.isRegisterOpen) return; | |
| if (deviceBusy) return; | |
| if (it.size === 0) { | |
| try { | |
| @@ -642,6 +476,8 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| cartDisplayAbortController.current = new AbortController(); | |
| } | |
| + const signal = cartDisplayAbortController.current.signal; | |
| + | |
| const cartItems = [...it.values()].map((lineItem) => { | |
| const cartItem: TransactionCartItem = { | |
| ...lineItem, | |
| @@ -653,62 +489,21 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| return cartItem; | |
| }); | |
| - const defaultPaymentMethodId = | |
| - selectedSalesChannel?.defaultPaymentMethodId; | |
| - const calculatedPaymentMethodTotals = Object.entries( | |
| - paymentMethodTypeToPaymentMethod, | |
| - ).reduce( | |
| - (acc, [paymentForm, paymentMethods]) => { | |
| - if (paymentMethods && paymentMethods.length > 0) { | |
| - // First filter for displayOnPayButton=true, then find the best method | |
| - const displayableMethods = paymentMethods.filter( | |
| - (method) => method.displayOnPayButton, | |
| - ); | |
| - const bestMethod = findBestPaymentMethod( | |
| - displayableMethods, | |
| - defaultPaymentMethodId, | |
| - ); | |
| - if (bestMethod) { | |
| - acc[paymentForm] = | |
| - paymentMethodIdToCartTotal[bestMethod.id] || | |
| - transactionTotalPrice({ paymentMethodId: bestMethod.id }); | |
| - } | |
| - } | |
| - return acc; | |
| - }, | |
| - {} as Record<string, number>, | |
| - ); | |
| - | |
| const s = async () => { | |
| return await setItemsInCartMutate({ | |
| items: cartItems, | |
| - paymentMethodTotals: overriddenCohortPriceLevel | |
| - ? {} | |
| - : calculatedPaymentMethodTotals, | |
| }); | |
| }; | |
| try { | |
| await s(); | |
| - } catch { | |
| + } catch (err) { | |
| // retry once on failure | |
| setTimeout(() => { | |
| s().catch(() => undefined); | |
| }, 300); | |
| } | |
| }, | |
| - [ | |
| - deviceBusy, | |
| - entity.id, | |
| - register.isRegisterOpen, | |
| - register.registerNumber, | |
| - emptyCart, | |
| - setItemsInCartMutate, | |
| - transactionTotalPrice, | |
| - paymentMethodTypeToPaymentMethod, | |
| - findBestPaymentMethod, | |
| - selectedSalesChannel?.defaultPaymentMethodId, | |
| - overriddenCohortPriceLevel, | |
| - ], | |
| + [deviceBusy, entity.id, register.isRegisterOpen, register.registerNumber], | |
| ); | |
| useBeforeUnload(() => { | |
| @@ -725,174 +520,14 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| useEffect(() => { | |
| if (!window.location.href.includes("sale")) return; | |
| - void setItemsInCart(debouncedItems ?? new Map(), debouncedTotals); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| - }, [debouncedItems, debouncedTotals]); | |
| - | |
| - const calculateBackgroundPaymentMethodTotals = useCallback( | |
| - async (opts: PricingRequestOptions) => { | |
| - if ( | |
| - overriddenCohortPriceLevel !== undefined || | |
| - !hasMultiplePriceLevelsOnSalesChannel | |
| - ) { | |
| - setPaymentMethodIdToCartTotal({}); | |
| - return; | |
| - } | |
| - | |
| - const { | |
| - requestedDiscount, | |
| - requestedCustomer, | |
| - requestTaxExempt, | |
| - requestedItems, | |
| - paymentMethodId, | |
| - } = opts; | |
| - console.log( | |
| - "calculateBackgroundPaymentMethodTotals paymentMethodId", | |
| - paymentMethodId, | |
| - ); | |
| - if (paymentMethodId !== undefined) { | |
| - return; | |
| - } | |
| - if (!requestedItems) throw new Error("Requested items are required"); | |
| - if (requestedItems.size === 0) { | |
| - setPaymentMethodIdToCartTotal({}); | |
| - return; | |
| - } | |
| - | |
| - // Abort any previous background calculation requests | |
| - if (!backgroundCalculationAbortController.current) { | |
| - backgroundCalculationAbortController.current = new AbortController(); | |
| - console.log("backgroundCalculationAbortController created"); | |
| - } else { | |
| - try { | |
| - backgroundCalculationAbortController.current.abort(); | |
| - console.log("backgroundCalculationAbortController aborted"); | |
| - } catch (e) { | |
| - console.warn(e); | |
| - } | |
| - backgroundCalculationAbortController.current = new AbortController(); | |
| - console.log("backgroundCalculationAbortController created"); | |
| - } | |
| - | |
| - const signal = backgroundCalculationAbortController.current.signal; | |
| - console.log("backgroundCalculationAbortController signal", signal); | |
| - setIsCalculatingBackgroundPaymentMethodTotals(true); | |
| - console.log("setIsCalculatingBackgroundPaymentMethodTotals true"); | |
| - try { | |
| - const nonDefaultPaymentMethods = | |
| - paymentMethods?.content?.filter( | |
| - (pm) => pm.id !== selectedSalesChannel.defaultPaymentMethodId, | |
| - ) ?? []; | |
| - | |
| - const paymentMethodIdToCartTotal: Record<string, number> = {}; | |
| - const cachedTotalz: Record<number, number> = {}; | |
| - console.log("nonDefaultPaymentMethods", nonDefaultPaymentMethods); | |
| - for (const paymentMethod of nonDefaultPaymentMethods) { | |
| - const cachedTotal = cachedTotalz[paymentMethod.cohortPriceLevelId]; | |
| - if (cachedTotal) { | |
| - paymentMethodIdToCartTotal[paymentMethod.id] = cachedTotal; | |
| - continue; | |
| - } | |
| - const pricingCartInputItems: PricingCartInputItem[] = []; | |
| - for (const lineItem of requestedItems.values()) { | |
| - if (lineItem.item?.ei_id === undefined) { | |
| - const unknownItem: UnknownItem = { | |
| - upc: lineItem.upcCode, | |
| - name: lineItem.name, | |
| - price: lineItem.price, | |
| - bottleDepositMultiplier: lineItem.bottleFeeMultiplier ?? 0, | |
| - envFeeMultiplier: lineItem.environmentFeeMultiplier ?? 0, | |
| - department: departmentKeyMap?.get(lineItem.department)?.id!, | |
| - }; | |
| - pricingCartInputItems.push({ | |
| - type: PricingCartInputItemType.unknownItem, | |
| - unknownItem: unknownItem, | |
| - transactionItemId: lineItem.id, | |
| - quantity: lineItem.quantity, | |
| - taxExempt: false, | |
| - }); | |
| - } else { | |
| - pricingCartInputItems.push( | |
| - convertToPricingCartInputItem({ | |
| - ...lineItem, | |
| - }), | |
| - ); | |
| - } | |
| - } | |
| - | |
| - const res = await getCartPricingRequest( | |
| - { | |
| - items: pricingCartInputItems, | |
| - transactionId: transactionId ?? 0, | |
| - discount: requestedDiscount, | |
| - governmentID: governmentID, | |
| - loyaltyCustomerId: requestedCustomer?.loyaltyCustomerId, | |
| - taxExempt: requestTaxExempt, | |
| - persistToTransaction: false, | |
| - salesChannelId: selectedSalesChannel.id, | |
| - overriddenPriceLevel: paymentMethod.cohortPriceLevelId, | |
| - }, | |
| - { signal }, | |
| - ); | |
| - console.log( | |
| - "getCartPricingRequest res", | |
| - res, | |
| - " for paymentMethod", | |
| - paymentMethod, | |
| - ); | |
| - // Check if we've been aborted before making the API call | |
| - if (signal.aborted) { | |
| - throw new CanceledError("Background calculation was canceled"); | |
| - } | |
| - const total = res.reduce((acc, item) => acc + item.total, 0); | |
| - paymentMethodIdToCartTotal[paymentMethod.id] = total; | |
| - cachedTotalz[paymentMethod.cohortPriceLevelId] = total; | |
| - } | |
| - | |
| - console.log("paymentMethodIdToCartTotal", paymentMethodIdToCartTotal); | |
| - setPaymentMethodIdToCartTotal(paymentMethodIdToCartTotal); | |
| - } catch (err) { | |
| - if (err instanceof CanceledError) { | |
| - console.warn("Background calculation was canceled"); | |
| - return; | |
| - } | |
| - captureException(err); | |
| - setPaymentMethodIdToCartTotal({}); | |
| - throw err; | |
| - } finally { | |
| - setIsCalculatingBackgroundPaymentMethodTotals(false); | |
| - console.log("setIsCalculatingBackgroundPaymentMethodTotals false"); | |
| - } | |
| - }, | |
| - [ | |
| - overriddenCohortPriceLevel, | |
| - paymentMethods, | |
| - governmentID, | |
| - selectedSalesChannel.id, | |
| - selectedSalesChannel.defaultPaymentMethodId, | |
| - transactionId, | |
| - hasMultiplePriceLevelsOnSalesChannel, | |
| - departmentKeyMap, | |
| - ], | |
| - ); | |
| + void setItemsInCart(debouncedItems ?? new Map()); | |
| + }, [debouncedItems, setItemsInCart]); | |
| const urgentCalculateCartPrice = useCallback( | |
| async (opts: PricingRequestOptions) => { | |
| if (cartPriceCallInProgress.current) return; | |
| - let { | |
| - requestedDiscount, | |
| - requestTaxExempt, | |
| - requestedCustomer, | |
| - paymentMethodId, | |
| - overriddenPriceLevel, | |
| - hasOverriddenPriceLevel, | |
| - } = opts; | |
| - | |
| - console.log( | |
| - "calculateCartPriceQueue length", | |
| - calculateCartPriceQueue.length, | |
| - ); | |
| + let { requestedDiscount, requestTaxExempt, requestedCustomer } = opts; | |
| // Get the latest item details. The previous ones are stale. | |
| const itemDetailz = calculateCartPriceQueue.pop(); | |
| @@ -936,7 +571,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| id: draftedTransactionItemId, | |
| }; | |
| - if (finalItem.item?.ei_variable_cost_percent) { | |
| + if (!!finalItem.item?.variableCostPct) { | |
| setAddingVariableCostItemId(finalItem.id); | |
| } | |
| itemDetailz.set(draftedTransactionItemId, finalItem); | |
| @@ -959,7 +594,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| const signal = cartPricingAbortController.current.signal; | |
| for (const lineItem of itemDetailz.values()) { | |
| - if (lineItem.item?.ei_id === undefined) { | |
| + if (lineItem.item?.id === undefined) { | |
| const unknownItem: UnknownItem = { | |
| upc: lineItem.upcCode, | |
| name: lineItem.name, | |
| @@ -987,18 +622,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| const getCartPricing = async () => { | |
| try { | |
| let newCalculationWarning = false; | |
| - | |
| - let requestedOverriddenPriceLevel = (() => { | |
| - if (hasOverriddenPriceLevel) { | |
| - return overriddenPriceLevel; | |
| - } | |
| - return undefined; | |
| - })(); | |
| - if (!requestedOverriddenPriceLevel) { | |
| - requestedOverriddenPriceLevel = paymentMethods?.content?.find( | |
| - (pm) => pm.id === paymentMethodId, | |
| - )?.cohortPriceLevelId; | |
| - } | |
| const response = await getCartPricingRequest( | |
| { | |
| items: pricingCartInputItems, | |
| @@ -1008,29 +631,15 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| loyaltyCustomerId: requestedCustomer?.loyaltyCustomerId, | |
| salesChannelId: selectedSalesChannel.id, | |
| taxExempt: requestTaxExempt, | |
| - overriddenPriceLevel: requestedOverriddenPriceLevel, | |
| }, | |
| { signal }, | |
| ); | |
| setIsGetCartPricingError(false); | |
| - const newItemDetailsArray = await Promise.all( | |
| - response.map(async (i: PricingCartOutputItem) => { | |
| + const newItemDetails = new Map( | |
| + response.map((i: PricingCartOutputItem) => { | |
| const prevLineItem = i.transactionItemId | |
| ? itemDetailz.get(i.transactionItemId) | |
| : undefined; | |
| - | |
| - const options = RetrieveItemsByUpcQuery( | |
| - entity.id, | |
| - null, | |
| - i.entityItem?.id ? [i.entityItem.id] : [], | |
| - ); | |
| - const eRes = i.entityItem | |
| - ? await db.query<RetrieveItemsByUpc>( | |
| - options.query, | |
| - options.params, | |
| - ) | |
| - : undefined; | |
| - | |
| const lineItem: LineItem = { | |
| ...i, | |
| upcCode: i.upc, | |
| @@ -1038,7 +647,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| tax: i.tax, | |
| taxRate: i.taxRate, | |
| calculationMetadata: i.calculationMetadata, | |
| - taxExempt: i.taxExempt ?? false, | |
| + taxExempt: false, | |
| totalPrice: i.total, | |
| promotionItems: i.promotionAmounts, | |
| discount: i.discount ?? 0, | |
| @@ -1047,13 +656,12 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| lineItemDiscount: prevLineItem?.lineItemDiscount, | |
| bottleFee: i.bottleDeposit, | |
| environmentFee: i.environmentFee, | |
| - item: eRes?.rows?.[0], | |
| + item: i.entityItem, | |
| itemId: i.entityItem?.id as number, | |
| transactionId: transactionId, | |
| department: i.department.id, | |
| id: i.transactionItemId, | |
| }; | |
| - | |
| if ( | |
| prevLineItem && | |
| !hasCalculationWarning(prevLineItem) && | |
| @@ -1061,11 +669,9 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| ) { | |
| newCalculationWarning = true; | |
| } | |
| - | |
| - return [lineItem.id, lineItem] as const; | |
| + return [lineItem.id, lineItem]; | |
| }), | |
| ); | |
| - const newItemDetails = new Map(newItemDetailsArray); | |
| // Show warning if any of the items have a warning | |
| if (newCalculationWarning && calculateCartPriceQueue.length === 0) { | |
| @@ -1092,19 +698,9 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| setCustomerState(requestedCustomer); | |
| setCartDiscount(requestedDiscount); | |
| setTaxExempt(requestTaxExempt); | |
| - if (paymentMethodId === undefined) { | |
| - // no override passed in directly | |
| - void calculateBackgroundPaymentMethodTotalsRef.current({ | |
| - requestedItems: newItemDetails, | |
| - requestTaxExempt: requestTaxExempt, | |
| - requestedCustomer: requestedCustomer, | |
| - requestedDiscount: requestedDiscount, | |
| - }); | |
| - } | |
| return newItemDetails; | |
| } | |
| calculateCartPriceQueue.push(newItemDetails); | |
| - | |
| throw new Error(cartPricingQueueNotEmptyMessage); | |
| } catch (err) { | |
| if (err instanceof CanceledError) { | |
| @@ -1170,28 +766,18 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| }); | |
| }, | |
| [ | |
| - entity.id, | |
| + entity?.id, | |
| departmentMap, | |
| departmentKeyMap, | |
| transactionId, | |
| draftTransactionItem, | |
| governmentID, | |
| selectedSalesChannel.id, | |
| - db, | |
| toast, | |
| - paymentMethods, | |
| ], | |
| ); | |
| const urgentCalculateCartPriceRef = useRef(urgentCalculateCartPrice); | |
| - const calculateBackgroundPaymentMethodTotalsRef = useRef( | |
| - calculateBackgroundPaymentMethodTotals, | |
| - ); | |
| - useEffect(() => { | |
| - calculateBackgroundPaymentMethodTotalsRef.current = | |
| - calculateBackgroundPaymentMethodTotals; | |
| - }, [calculateBackgroundPaymentMethodTotals]); | |
| - | |
| useEffect(() => { | |
| urgentCalculateCartPriceRef.current = urgentCalculateCartPrice; | |
| }, [urgentCalculateCartPrice]); | |
| @@ -1205,7 +791,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| calculateCartPriceQueue.push(itemz); | |
| setIsCalculatingCartPrice(true); | |
| const output = await urgentCalculateCartPriceRef.current(opts); | |
| - | |
| setIsCalculatingCartPrice(false); | |
| if (output === undefined) { | |
| throw new Error("Cart price calculation failed"); | |
| @@ -1217,21 +802,18 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| const isPriceAtCost = customer?.priceAtCost ?? false; | |
| - const isEntityItemDetail = useCallback( | |
| - ( | |
| - itemDetailz: | |
| - | RetrieveItemsByUpc | |
| - | Omit<DraftTransactionItemInput, "transactionId">, | |
| - ): itemDetailz is RetrieveItemsByUpc => { | |
| - return "ei_id" in itemDetailz; | |
| - }, | |
| - [], | |
| - ); | |
| + const isEntityItemDetail = ( | |
| + itemDetailz: | |
| + | EntityItemDetail | |
| + | Omit<DraftTransactionItemInput, "transactionId">, | |
| + ): itemDetailz is EntityItemDetail => { | |
| + return "cohortItem" in itemDetailz; | |
| + }; | |
| const addSingleItemToCart = useCallback( | |
| async ( | |
| itemDetailz: | |
| - | RetrieveItemsByUpc | |
| + | EntityItemDetail | |
| | Omit<DraftTransactionItemInput, "transactionId">, | |
| quantity = 1, | |
| ) => { | |
| @@ -1300,7 +882,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| }, | |
| [ | |
| transactionId, | |
| - isEntityItemDetail, | |
| taxExempt, | |
| isPriceAtCost, | |
| calculateCartPrice, | |
| @@ -1317,7 +898,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| }, [items, lineItemDiscounts]); | |
| const handleRetrievedItems = useCallback( | |
| - async (items: RetrieveItemsByUpc[], quantity: number = 1) => { | |
| + async (items: EntityItemDetail[], quantity: number = 1) => { | |
| try { | |
| if (items.length === 1) { | |
| const item = items[0]; | |
| @@ -1340,59 +921,29 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| console.error(err); | |
| } | |
| }, | |
| - [addSingleItemToCart], | |
| + [addSingleItemToCart, setMultipleChoices], | |
| ); | |
| const retrieveItemsLikeUpc = useCallback( | |
| async (barCode: string, exact = false, quantity = 1) => { | |
| + // AbortController setup | |
| + // https://chat.openai.com/share/c9dca7d2-cef9-4cef-a47a-8cc30613ba63 | |
| + | |
| + const signal = retrieveUpcAbortController.current.signal; | |
| + | |
| setQuantity(1); | |
| try { | |
| - const startTime = performance.now(); | |
| - const options = RetrieveItemsByUpcQuery( | |
| - entity.id, | |
| - exact ? barCode : `%${barCode}%`, | |
| - null, | |
| - ); | |
| - console.log("options", options.query, options.params); | |
| - const eRes = await db.query<RetrieveItemsByUpc>( | |
| - options.query, | |
| - options.params, | |
| - ); | |
| - const opt = retrieveItemsLikeUpcQueryOptions({ | |
| - entityId: entity.id, | |
| - upcCode: exact ? barCode : `%${barCode}%`, | |
| - }); | |
| - queryClient | |
| - .fetchQuery(opt) | |
| - .then((res) => { | |
| - // if res != eRes, log to posthog | |
| - // this is to track any discrepancies between pg-lite and spring backend | |
| - // we can remove this after a few weeks of logging | |
| - if ( | |
| - !isEqual( | |
| - res.map((r) => r.id).toSorted((a, b) => a - b), | |
| - eRes.rows.map((r) => r.ei_id).toSorted((a, b) => a - b), | |
| - ) | |
| - ) { | |
| - posthog.capture("pg_lite_spring_backend_discrepancy", { | |
| - entityId: entity.id, | |
| - upcCode: exact ? barCode : `%${barCode}%`, | |
| - pgLiteCount: eRes.rows.length, | |
| - springBackendCount: res.length, | |
| - pgLiteItems: eRes.rows, | |
| - springBackendItems: res, | |
| - }); | |
| - } | |
| - }) | |
| - .catch((err) => { | |
| - captureException(err); | |
| - }); | |
| - const endTime = performance.now(); | |
| - console.log( | |
| - `Retrieved ${JSON.stringify(eRes)} electric items in ${endTime - startTime}ms`, | |
| + const retrieveItemUpcOptions = retrieveItemsLikeUpcQueryOptions( | |
| + { | |
| + upcCode: exact ? barCode : `%${barCode}%`, | |
| + entityId: entity.id, | |
| + }, | |
| + { | |
| + signal: signal, | |
| + }, | |
| ); | |
| - | |
| - await handleRetrievedItems(eRes.rows, quantity); | |
| + const res = await queryClient.fetchQuery(retrieveItemUpcOptions); | |
| + await handleRetrievedItems(res, quantity); | |
| } catch (err: any) { | |
| if (err instanceof CanceledError) { | |
| console.warn(err); | |
| @@ -1402,7 +953,7 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| console.error(err.message); | |
| } | |
| }, | |
| - [entity.id, db, queryClient, handleRetrievedItems], | |
| + [queryClient, entity.id, handleRetrievedItems], | |
| ); | |
| const calculateCartPriceRef = useRef(calculateCartPrice); | |
| @@ -1419,18 +970,21 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| setCustomerState(undefined); | |
| setCartDiscount(undefined); | |
| setIsGetCartPricingError(false); | |
| - setIsCalculatingBackgroundPaymentMethodTotals(false); | |
| - setPaymentMethodIdToCartTotal({}); | |
| lastPricingRequestId.current = null; | |
| retrieveUpcAbortController.current.abort(); | |
| retrieveUpcAbortController.current = new AbortController(); | |
| cartDisplayAbortController.current?.abort(); | |
| cartDisplayAbortController.current = new AbortController(); | |
| cartPriceCallInProgress.current = false; | |
| - backgroundCalculationAbortController.current?.abort(); | |
| - backgroundCalculationAbortController.current = new AbortController(); | |
| setSelectedItems(new Map()); | |
| - }, [resetSalesChannel]); | |
| + }, [ | |
| + resetSalesChannel, | |
| + setItems, | |
| + setTaxExempt, | |
| + setGovernmentID, | |
| + setCartDiscount, | |
| + setSelectedItems, | |
| + ]); | |
| const setAndDraftGovernmentID = useCallback( | |
| async (id?: GovernmentId) => { | |
| @@ -1452,24 +1006,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| [toast], | |
| ); | |
| - // Helper function to calculate methods with prices | |
| - const calculateMethodsWithPrices = useCallback( | |
| - (paymentForm: TransactionPaymentForm) => { | |
| - const paymentMethods = | |
| - paymentMethodTypeToPaymentMethod[paymentForm] || []; | |
| - | |
| - const seenPrices = new Set<number>(); | |
| - return paymentMethods | |
| - .filter((paymentMethod) => paymentMethod != null) | |
| - .map((paymentMethod) => ({ | |
| - method: paymentMethod, | |
| - total: transactionTotalPrice({ paymentMethodId: paymentMethod.id }), | |
| - })) | |
| - .filter(({ total }) => total !== undefined && total > 0); | |
| - }, | |
| - [paymentMethodTypeToPaymentMethod, transactionTotalPrice], | |
| - ); | |
| - | |
| if (!register.isRegisterOpen) { | |
| return <Navigate to={"/register/open/"} replace />; | |
| } | |
| @@ -1497,9 +1033,8 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| handleRetrievedItems, | |
| retrieveItemsLikeUpc, | |
| setItemsInCart, | |
| - resetCartToCurrentItems: async () => { | |
| - await setItemsInCart(debouncedItems ?? new Map(), debouncedTotals); | |
| - }, | |
| + resetCartToCurrentItems: () => | |
| + setItemsInCart(debouncedItems ?? new Map()), | |
| clearCart, | |
| multipleChoices, | |
| setMultipleChoices, | |
| @@ -1512,12 +1047,6 @@ export const SalesContextProvider: React.FC<SalesContextProviderProps> = ({ | |
| draftTransaction, | |
| isCalculatingCartPrice, | |
| isGetCartPricingError, | |
| - paymentMethodTypeToPaymentMethod: paymentMethodTypeToPaymentMethod, | |
| - isCalculatingBackgroundPaymentMethodTotals, | |
| - hasMultiplePriceLevelsOnSalesChannel, | |
| - calculateMethodsWithPrices, | |
| - findBestPaymentMethod, | |
| - setSkipSetItemsInCart, | |
| }} | |
| > | |
| {children} | |
| diff --git a/src/context/Sales/SalesPaymentContext.tsx b/src/context/Sales/SalesPaymentContext.tsx | |
| index d4a99e37..76a75b6d 100644 | |
| --- a/src/context/Sales/SalesPaymentContext.tsx | |
| +++ b/src/context/Sales/SalesPaymentContext.tsx | |
| @@ -37,10 +37,7 @@ import { | |
| usePayLaterTransaction, | |
| useProcessTransactionSale, | |
| } from "src/generated"; | |
| -import { | |
| - EntitySalesChannel, | |
| - EntitySalesChannelPaymentMethod, | |
| -} from "src/spring-generated"; | |
| +import { EntitySalesChannel } from "src/spring-generated"; | |
| import { useSessionStorage } from "usehooks-ts"; | |
| import useCashDrawer from "../../components/CashDrawer"; | |
| import { CreditSaleModalV2 } from "../../components/SalesScreenComponents/Modals/CreditCardSaleModalV2"; | |
| @@ -66,7 +63,6 @@ export type AmountReceived = { | |
| giftCardAmountReceived?: number; | |
| pointsAmountReceived?: number; | |
| paymentForm: TransactionPaymentForm; | |
| - paymentMethodId?: string; | |
| giftCardId?: string; | |
| creditCardId?: string; | |
| salesChannel?: TransactionSalesChannel; | |
| @@ -97,14 +93,8 @@ export interface SalesPaymentContextType { | |
| setGovernmentID: ( | |
| id: SalesPaymentContextType["governmentID"], | |
| ) => void | Promise<void>; | |
| - transactionTotalPrice: (options?: { | |
| - items?: SalesContextType["items"]; | |
| - paymentMethodId?: string; | |
| - }) => number; | |
| - creditCardPaid: ( | |
| - confirmationNeeded?: boolean, | |
| - paymentMethodId?: string, | |
| - ) => void; | |
| + transactionTotalPrice: (itemz?: SalesContextType["items"]) => number; | |
| + creditCardPaid: (confirmationNeeded?: boolean) => void; | |
| amountReceived?: AmountReceived; | |
| setAmountPaid: Dispatch<SetStateAction<AmountReceived | undefined>>; | |
| lastReceiptId?: number; | |
| @@ -122,29 +112,9 @@ export interface SalesPaymentContextType { | |
| salesChannel: EntitySalesChannel; | |
| isProcessSaleRequested: boolean; | |
| isCalculatingCartPrice?: boolean; | |
| - isGetCartPricingError?: boolean; | |
| salePaymentType: SalePaymentType; | |
| creditCardPaidPending: boolean; | |
| reviewTransactionModalPending: boolean; | |
| - calculateCartPrice?: (() => Promise<SalesContextType["items"]>) | undefined; | |
| - selectedCashPaymentMethodId?: string; | |
| - setSelectedCashPaymentMethodId: React.Dispatch< | |
| - React.SetStateAction<string | undefined> | |
| - >; | |
| - // Payment method functions (passed through from SalesContext) | |
| - paymentMethodTypeToPaymentMethod: Record< | |
| - string, | |
| - Array<EntitySalesChannelPaymentMethod> | |
| - >; | |
| - calculateMethodsWithPrices: ( | |
| - paymentForm: TransactionPaymentForm, | |
| - ) => Array<{ method: EntitySalesChannelPaymentMethod; total: number }>; | |
| - findBestPaymentMethod: ( | |
| - paymentMethods: EntitySalesChannelPaymentMethod[] | undefined, | |
| - defaultPaymentMethodId?: string, | |
| - ) => EntitySalesChannelPaymentMethod | null; | |
| - isCalculatingBackgroundPaymentMethodTotals: boolean; | |
| - selectedSalesChannel?: EntitySalesChannel; // From SalesContext/SalePageConfig | |
| } | |
| export const SalesPaymentContext = createContext< | |
| @@ -167,11 +137,8 @@ export interface SalesPaymentProviderProps { | |
| setTransactionId: ( | |
| transactionId?: TransactionId, | |
| ) => Promise<DraftTransactionMutationResponse | undefined>; | |
| - transactionTotalPrice: (options?: { | |
| - items?: SalesContextType["items"]; | |
| - paymentMethodId?: string; | |
| - }) => number; | |
| - resetCartToCurrentItems: () => Promise<void> | void; | |
| + transactionTotalPrice: () => number; | |
| + resetCartToCurrentItems: () => void; | |
| clearCart: () => void | Promise<void>; | |
| governmentID?: GovernmentId; | |
| setGovernmentID: ( | |
| @@ -179,31 +146,12 @@ export interface SalesPaymentProviderProps { | |
| ) => void | Promise<void>; | |
| customer?: LoyaltyCustomer; | |
| salesChannel: EntitySalesChannel; | |
| - overriddenCohortPriceLevel?: number; | |
| reviewTransactionModal?: UseDisclosureReturn; | |
| isCalculatingCartPrice?: boolean; | |
| payAfterConfirm: boolean; | |
| salePaymentType: SalePaymentType; | |
| isGetCartPricingError?: boolean; | |
| baseAmountReceived?: AmountReceived; | |
| - calculateCartPrice?: ( | |
| - paymentMethodId?: string, | |
| - ) => Promise<SalesContextType["items"]>; | |
| - // Payment method functions (passed through from SalesContext) | |
| - paymentMethodTypeToPaymentMethod: Record< | |
| - string, | |
| - Array<EntitySalesChannelPaymentMethod> | |
| - >; | |
| - calculateMethodsWithPrices: ( | |
| - paymentForm: TransactionPaymentForm, | |
| - ) => Array<{ method: EntitySalesChannelPaymentMethod; total: number }>; | |
| - findBestPaymentMethod: ( | |
| - paymentMethods: EntitySalesChannelPaymentMethod[] | undefined, | |
| - defaultPaymentMethodId?: string, | |
| - ) => EntitySalesChannelPaymentMethod | null; | |
| - isCalculatingBackgroundPaymentMethodTotals: boolean; | |
| - selectedSalesChannel?: EntitySalesChannel; // From SalesContext/SalePageConfig | |
| - setSkipSetItemsInCart: (skip: boolean) => void; | |
| } | |
| export const SalesPaymentProvider = ( | |
| @@ -211,7 +159,6 @@ export const SalesPaymentProvider = ( | |
| ) => { | |
| const { | |
| salesChannel, | |
| - overriddenCohortPriceLevel, | |
| transactionTotalPrice, | |
| transactionItems, | |
| clearCart, | |
| @@ -226,19 +173,11 @@ export const SalesPaymentProvider = ( | |
| isCalculatingCartPrice, | |
| isGetCartPricingError, | |
| baseAmountReceived, | |
| - calculateCartPrice, | |
| - paymentMethodTypeToPaymentMethod, | |
| - calculateMethodsWithPrices, | |
| - findBestPaymentMethod, | |
| - isCalculatingBackgroundPaymentMethodTotals, | |
| - selectedSalesChannel, | |
| - setSkipSetItemsInCart, | |
| } = props; | |
| // APIs | |
| const [isProcessSaleRequested, setIsProcessSaleRequested] = useState(false); | |
| - const [selectedCashPaymentMethodId, setSelectedCashPaymentMethodId] = | |
| - useState<string | undefined>(); | |
| + | |
| const { mutateAsync: draftTransactionPayment } = useDraftTransactionPayment(); | |
| const { mutateAsync: processTransactionSale } = useProcessTransactionSale({ | |
| mutation: { | |
| @@ -313,16 +252,7 @@ export const SalesPaymentProvider = ( | |
| [_setAmountPaid, baseAmountReceived], | |
| ); | |
| - const [isPersisting, _setIsPersisting] = useState(false); | |
| - | |
| - const setIsPersisting = useCallback( | |
| - (isPersisting: boolean) => { | |
| - _setIsPersisting(isPersisting); | |
| - setSkipSetItemsInCart(isPersisting); | |
| - }, | |
| - [_setIsPersisting, setSkipSetItemsInCart], | |
| - ); | |
| - | |
| + const [isPersisting, setIsPersisting] = useState(false); | |
| const [lastReceiptId, setLastReceiptId] = useSessionStorage< | |
| number | undefined | |
| >("lastReceiptId", undefined); | |
| @@ -402,11 +332,8 @@ export const SalesPaymentProvider = ( | |
| onlineAmountReceived + | |
| pointsAmountReceived + | |
| doordashAmountReceived; | |
| - const totalPrice = transactionTotalPrice({ | |
| - paymentMethodId: amountReceived?.paymentMethodId, | |
| - }); | |
| - if (amountTendered >= totalPrice) { | |
| - return amountTendered - totalPrice; | |
| + if (amountTendered >= transactionTotalPrice()) { | |
| + return amountTendered - transactionTotalPrice(); | |
| } | |
| return 0; | |
| }, | |
| @@ -518,12 +445,8 @@ export const SalesPaymentProvider = ( | |
| reviewTransactionModalOnClose(); | |
| creditCardModalV2OnClose(); | |
| void onSettledTransactionRef.current(); | |
| - await resetCartToCurrentItems(); | |
| - if (calculateCartPrice) { | |
| - await calculateCartPrice(); | |
| - } | |
| + resetCartToCurrentItems(); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| creditCardModalV2OnClose, | |
| resetCartToCurrentItems, | |
| @@ -544,7 +467,6 @@ export const SalesPaymentProvider = ( | |
| }); | |
| setAmountPaid(undefined); | |
| setIsPersisting(false); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [queryClient]); | |
| const onSettledTransactionRef = useRef(onSettledTransaction); | |
| @@ -574,12 +496,7 @@ export const SalesPaymentProvider = ( | |
| if (!register.isRegisterOpen) return; | |
| if (isPersisting) return; | |
| - const transactionTotalPriceCalled = round( | |
| - transactionTotalPrice({ | |
| - paymentMethodId: amountReceived?.paymentMethodId, | |
| - }), | |
| - 2, | |
| - ); | |
| + const transactionTotalPriceCalled = round(transactionTotalPrice(), 2); | |
| const summedAmountPaid = round( | |
| amountPaid + | |
| creditCardAmountReceived + | |
| @@ -622,10 +539,6 @@ export const SalesPaymentProvider = ( | |
| ); | |
| try { | |
| setIsPersisting(true); | |
| - if (calculateCartPrice && overriddenCohortPriceLevel === undefined) { | |
| - await calculateCartPrice(amountReceived?.paymentMethodId); | |
| - } | |
| - | |
| await draftTransactionPayment({ | |
| transactionId: transactionIdCur, | |
| registerNumber: register.registerNumber, | |
| @@ -748,13 +661,11 @@ export const SalesPaymentProvider = ( | |
| setIsPersisting(false); | |
| setIsProcessSaleRequested(false); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| amountReceived, | |
| register.isRegisterOpen, | |
| register.registerNumber, | |
| isPersisting, | |
| - setIsPersisting, | |
| transactionTotalPrice, | |
| draftTransactionPayment, | |
| payLaterTransaction, | |
| @@ -780,22 +691,15 @@ export const SalesPaymentProvider = ( | |
| persistTransactionRef.current = persistTransaction; | |
| }, [persistTransaction]); | |
| - const _creditCardPaid = useCallback( | |
| - (confirmationNeeded?: boolean, paymentMethodId?: string) => { | |
| - setAmountPaid({ | |
| - amountPaid: 0, | |
| - creditCardAmountReceived: transactionTotalPrice({ | |
| - paymentMethodId, | |
| - }), | |
| - paymentForm: TransactionPaymentForm["CREDIT CARD"], | |
| - paymentMethodId, | |
| - }); | |
| + const _creditCardPaid = useCallback(() => { | |
| + setAmountPaid({ | |
| + amountPaid: 0, | |
| + creditCardAmountReceived: transactionTotalPrice(), | |
| + paymentForm: TransactionPaymentForm["CREDIT CARD"], | |
| + }); | |
| - reviewTransactionModalOnOpen(); | |
| - }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| - [transactionTotalPrice, reviewTransactionModalOnOpen], | |
| - ); | |
| + reviewTransactionModalOnOpen(); | |
| + }, [transactionTotalPrice, reviewTransactionModalOnOpen]); | |
| const { | |
| trigger: creditCardPaid, | |
| @@ -814,7 +718,6 @@ export const SalesPaymentProvider = ( | |
| if (transactionItems.length === 0) { | |
| setAmountPaid(undefined); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [transactionItems]); | |
| useEffect(() => { | |
| @@ -854,14 +757,6 @@ export const SalesPaymentProvider = ( | |
| persistPending, | |
| creditCardPaidPending, | |
| reviewTransactionModalPending, | |
| - calculateCartPrice, | |
| - selectedCashPaymentMethodId, | |
| - setSelectedCashPaymentMethodId, | |
| - paymentMethodTypeToPaymentMethod, | |
| - calculateMethodsWithPrices, | |
| - findBestPaymentMethod, | |
| - isCalculatingBackgroundPaymentMethodTotals, | |
| - selectedSalesChannel, | |
| }} | |
| > | |
| <> | |
| @@ -870,7 +765,6 @@ export const SalesPaymentProvider = ( | |
| isOpen={payWithCashModal.isOpen} | |
| onClose={payWithCashModal.onClose} | |
| openChangeDueModal={reviewTransactionModal.onOpen} | |
| - selectedCashPaymentMethodId={selectedCashPaymentMethodId} | |
| /> | |
| <ReviewSaleModal | |
| {...reviewTransactionModal} | |
| diff --git a/src/context/StorefrontContext/StorefrontContext.tsx b/src/context/StorefrontContext/StorefrontContext.tsx | |
| deleted file mode 100644 | |
| index e09a94ee..00000000 | |
| --- a/src/context/StorefrontContext/StorefrontContext.tsx | |
| +++ /dev/null | |
| @@ -1,7 +0,0 @@ | |
| -import { createContext } from "react"; | |
| - | |
| -export interface StorefrontContext {} | |
| - | |
| -export const StorefrontContext = createContext<StorefrontContext | undefined>( | |
| - undefined, | |
| -); | |
| diff --git a/src/context/StorefrontContext/StorefrontProvider.tsx b/src/context/StorefrontContext/StorefrontProvider.tsx | |
| deleted file mode 100644 | |
| index 7608245c..00000000 | |
| --- a/src/context/StorefrontContext/StorefrontProvider.tsx | |
| +++ /dev/null | |
| @@ -1,122 +0,0 @@ | |
| -import { Button } from "components/ui/button"; | |
| -import { toast } from "components/ui/use-toast"; | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useStorefrontDecisionHandler } from "hooks/useStorefrontDecisionHandler"; | |
| -import { ShoppingCart } from "lucide-react"; | |
| -import { useCallback, useEffect, useRef } from "react"; | |
| -import { | |
| - getTransactionByTransactionItem, | |
| - WebsocketBroadcastMessagePayload, | |
| -} from "src/phoenix-generated"; | |
| -import { playNotificationSound } from "../../utils/audioUtils"; | |
| -import { StorefrontContext } from "./StorefrontContext"; | |
| - | |
| -export interface StorefrontProviderProps { | |
| - children: React.ReactNode; | |
| -} | |
| - | |
| -export const StorefrontProvider: React.FC<StorefrontProviderProps> = ({ | |
| - children, | |
| -}) => { | |
| - const notifiedTransactions = useRef(new Map<string, () => void>()); | |
| - const cleanupTimeouts = useRef(new Map<string, NodeJS.Timeout>()); | |
| - const onOrderItemDecision = useCallback( | |
| - async (event: WebsocketBroadcastMessagePayload) => { | |
| - if (!event.orderItemDecision) { | |
| - return; | |
| - } | |
| - const transaction = await getTransactionByTransactionItem( | |
| - event.orderItemDecision.transaction_item_id, | |
| - ).catch((err) => { | |
| - captureException(err); | |
| - return null; | |
| - }); | |
| - if (!transaction) { | |
| - return; | |
| - } | |
| - | |
| - const transactionId = transaction.id.toString(); | |
| - | |
| - // Play notification sound only if we haven't already notified for this transaction | |
| - if ( | |
| - event.orderItemDecision.status === "CREATED" && | |
| - !notifiedTransactions.current.has(transactionId) | |
| - ) { | |
| - void playNotificationSound(); | |
| - const { dismiss } = toast({ | |
| - id: transactionId, | |
| - duration: Infinity, | |
| - className: "bg-blue-600 text-white border-blue-500", | |
| - title: "New Online Order", | |
| - description: ( | |
| - <div className="flex items-start gap-3 mt-1"> | |
| - <ShoppingCart className="h-5 w-5 text-white mt-0.5" /> | |
| - <div className="flex flex-col gap-1"> | |
| - <p> | |
| - Order ID:{" "} | |
| - <span className="font-mono font-medium"> | |
| - {transaction.id} | |
| - </span> | |
| - </p> | |
| - <p className="text-blue-100"> | |
| - Order Date:{" "} | |
| - {transaction.paidAt | |
| - ? new Date(transaction.paidAt).toLocaleString() | |
| - : "N/A"} | |
| - </p> | |
| - </div> | |
| - </div> | |
| - ), | |
| - action: ( | |
| - <Button | |
| - variant="outline" | |
| - className="border-white text-white hover:bg-white/10" | |
| - asChild | |
| - > | |
| - <a href={`/transaction/${transaction.id}`}>View Order</a> | |
| - </Button> | |
| - ), | |
| - }); | |
| - notifiedTransactions.current.set(transactionId, dismiss); | |
| - | |
| - // Set up cleanup to remove the transaction ID after 5 minutes | |
| - const timeoutId = setTimeout(() => { | |
| - notifiedTransactions.current.delete(transactionId); | |
| - cleanupTimeouts.current.delete(transactionId); | |
| - }, 300000); | |
| - | |
| - cleanupTimeouts.current.set(transactionId, timeoutId); | |
| - } else if ( | |
| - ["ACCEPTED", "REJECTED"].includes(event.orderItemDecision.status) | |
| - ) { | |
| - notifiedTransactions.current.get(transactionId)?.(); | |
| - notifiedTransactions.current.delete(transactionId); | |
| - cleanupTimeouts.current.delete(transactionId); | |
| - } | |
| - }, | |
| - [], | |
| - ); | |
| - | |
| - // TODO: enabled only if storefront exists | |
| - useStorefrontDecisionHandler(true, onOrderItemDecision); | |
| - | |
| - // Cleanup timeouts on unmount | |
| - useEffect(() => { | |
| - const currentCleanupTimeouts = cleanupTimeouts.current; | |
| - const currentNotifiedTransactions = notifiedTransactions.current; | |
| - return () => { | |
| - // Clear all pending timeouts when component unmounts | |
| - currentCleanupTimeouts.forEach((timeoutId) => { | |
| - clearTimeout(timeoutId); | |
| - }); | |
| - currentCleanupTimeouts.clear(); | |
| - currentNotifiedTransactions.clear(); | |
| - }; | |
| - }, []); | |
| - | |
| - return ( | |
| - <StorefrontContext.Provider value={{}}> | |
| - {children} | |
| - </StorefrontContext.Provider> | |
| - ); | |
| -}; | |
| diff --git a/src/context/WebsocketContext/WebsocketContext.tsx b/src/context/WebsocketContext/WebsocketContext.tsx | |
| deleted file mode 100644 | |
| index 55be98b1..00000000 | |
| --- a/src/context/WebsocketContext/WebsocketContext.tsx | |
| +++ /dev/null | |
| @@ -1,41 +0,0 @@ | |
| -import { createContext } from "react"; | |
| -import { ReadyState } from "react-use-websocket"; | |
| -import { | |
| - WebsocketBroadcastMessagePayload, | |
| - WebsocketWebsocketMessageType, | |
| -} from "src/phoenix-generated"; | |
| - | |
| -export type EventTypeMap = { | |
| - [WebsocketWebsocketMessageType.ConnectionInfoRequest]: { | |
| - type: WebsocketWebsocketMessageType.ConnectionInfoRequest; | |
| - }; | |
| - [WebsocketWebsocketMessageType.ConnectionInfoResponse]: WebsocketBroadcastMessagePayload["connectionInfo"]; | |
| - [WebsocketWebsocketMessageType.OrderItemDecision]: WebsocketBroadcastMessagePayload["orderItemDecision"]; | |
| - [WebsocketWebsocketMessageType.PING]: { | |
| - type: WebsocketWebsocketMessageType.PING; | |
| - }; | |
| - [WebsocketWebsocketMessageType.PONG]: { | |
| - type: WebsocketWebsocketMessageType.PONG; | |
| - }; | |
| -}; | |
| -export type EventType = keyof EventTypeMap; | |
| -export type EventPayload<T extends EventType> = EventTypeMap[T] & { type: T }; | |
| - | |
| -export type WebsocketContext = { | |
| - readyState: ReadyState; | |
| - subscribe: <T extends EventType>( | |
| - eventType: T, | |
| - callback: (payload: WebsocketBroadcastMessagePayload) => void, | |
| - ) => void; | |
| - unsubscribe: <T extends EventType>( | |
| - eventType: T, | |
| - callback: (payload: WebsocketBroadcastMessagePayload) => void, | |
| - ) => void; | |
| - sendMessage: <T extends EventType>(payload: EventPayload<T>) => void; | |
| - emit: <T extends EventType>(eventType: T, payload: EventPayload<T>) => void; | |
| - connectionId: string | null; | |
| -}; | |
| - | |
| -export const WebsocketContext = createContext<WebsocketContext | undefined>( | |
| - undefined, | |
| -); | |
| diff --git a/src/context/WebsocketContext/WebsocketProvider.tsx b/src/context/WebsocketContext/WebsocketProvider.tsx | |
| deleted file mode 100644 | |
| index 2508b652..00000000 | |
| --- a/src/context/WebsocketContext/WebsocketProvider.tsx | |
| +++ /dev/null | |
| @@ -1,189 +0,0 @@ | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useCallback, useEffect, useRef, useState } from "react"; | |
| -import useWebSocket, { ReadyState } from "react-use-websocket"; | |
| -import { | |
| - WebsocketBroadcastMessagePayload, | |
| - WebsocketWebsocketMessageType, | |
| -} from "src/phoenix-generated"; | |
| -import { useInterval } from "usehooks-ts"; | |
| -import { EventPayload } from "."; | |
| -import { EventType, WebsocketContext } from "./WebsocketContext"; | |
| - | |
| -export interface WebsocketProviderProps { | |
| - children: React.ReactNode; | |
| -} | |
| - | |
| -const WS_URL = | |
| - import.meta.env.VITE_WS_URL ?? | |
| - "wss://n3t271qwr5.execute-api.us-east-1.amazonaws.com/$default"; | |
| -const shouldAttemptConnection = true; | |
| - | |
| -export const WebsocketProvider: React.FC<WebsocketProviderProps> = ({ | |
| - children, | |
| -}) => { | |
| - const eventListeners = useRef< | |
| - Map<EventType, Set<(payload: WebsocketBroadcastMessagePayload) => void>> | |
| - >(new Map()); | |
| - const [connectionId, setConnectionId] = useState<string | null>(null); | |
| - | |
| - const subscribe = useCallback( | |
| - <T extends EventType>( | |
| - eventType: T, | |
| - callback: (payload: WebsocketBroadcastMessagePayload) => void, | |
| - ) => { | |
| - if (!eventListeners.current.has(eventType)) { | |
| - eventListeners.current.set(eventType, new Set()); | |
| - } | |
| - eventListeners.current.get(eventType)!.add(callback); | |
| - }, | |
| - [], | |
| - ); | |
| - | |
| - const unsubscribe = useCallback( | |
| - <T extends EventType>( | |
| - eventType: T, | |
| - callback: (payload: WebsocketBroadcastMessagePayload) => void, | |
| - ) => { | |
| - const listeners = eventListeners.current.get(eventType); | |
| - if (listeners) { | |
| - listeners.delete(callback); | |
| - if (listeners.size === 0) { | |
| - eventListeners.current.delete(eventType); | |
| - } | |
| - } | |
| - }, | |
| - [], | |
| - ); | |
| - | |
| - const emit = useCallback( | |
| - <T extends EventType>( | |
| - eventType: T, | |
| - payload: WebsocketBroadcastMessagePayload, | |
| - ) => { | |
| - const listeners = eventListeners.current.get(eventType); | |
| - if (listeners) { | |
| - listeners.forEach((callback) => { | |
| - try { | |
| - callback(payload); | |
| - } catch (error) { | |
| - console.error(`Error in event listener for ${eventType}:`, error); | |
| - } | |
| - }); | |
| - } | |
| - }, | |
| - [], | |
| - ); | |
| - | |
| - const onMessage = useCallback( | |
| - (event: MessageEvent) => { | |
| - try { | |
| - const message: WebsocketBroadcastMessagePayload = JSON.parse( | |
| - event.data, | |
| - ); | |
| - console.log("Received WebSocket message", message); | |
| - | |
| - if (message) { | |
| - emit(message.type, message); | |
| - } | |
| - } catch (error) { | |
| - console.error("Error parsing WebSocket message:", error); | |
| - } | |
| - }, | |
| - [emit], | |
| - ); | |
| - | |
| - const { sendJsonMessage: _sendMessage, readyState } = useWebSocket( | |
| - WS_URL, | |
| - { | |
| - onClose: (event) => { | |
| - console.log("Connection closed", event); | |
| - }, | |
| - shouldReconnect: () => true, | |
| - onOpen: (event) => { | |
| - console.log("Connection opened", event); | |
| - }, | |
| - onMessage, | |
| - onReconnectStop: (numAttempts) => { | |
| - console.log("Reconnect stopped", numAttempts); | |
| - }, | |
| - reconnectInterval: 0, | |
| - reconnectAttempts: 2, | |
| - }, | |
| - shouldAttemptConnection, | |
| - ); | |
| - | |
| - const sendMessage = useCallback( | |
| - <T extends EventType>(payload: EventPayload<T>) => { | |
| - if (readyState === ReadyState.OPEN) { | |
| - _sendMessage(payload); | |
| - } else { | |
| - console.warn( | |
| - `Cannot send message - WebSocket not ready. State: ${readyState}`, | |
| - ); | |
| - } | |
| - }, | |
| - [_sendMessage, readyState], | |
| - ); | |
| - | |
| - // ping every minute (heartbeat) | |
| - useInterval( | |
| - () => { | |
| - if (readyState === ReadyState.OPEN) | |
| - sendMessage({ | |
| - type: WebsocketWebsocketMessageType.PING, | |
| - }); | |
| - }, | |
| - 1000 * 60 * 1, | |
| - ); | |
| - | |
| - // request connection info from server once we are connected | |
| - useEffect(() => { | |
| - if (readyState === ReadyState.OPEN) { | |
| - sendMessage({ | |
| - type: WebsocketWebsocketMessageType.ConnectionInfoRequest, | |
| - }); | |
| - } | |
| - }, [readyState, sendMessage]); | |
| - | |
| - const handleConnectionInfo = useCallback( | |
| - (payload: WebsocketBroadcastMessagePayload) => { | |
| - if (!payload?.connectionInfo?.connectionId) { | |
| - captureException( | |
| - new Error("Connection info response received without connection id"), | |
| - ); | |
| - return; | |
| - } | |
| - setConnectionId(payload.connectionInfo.connectionId); | |
| - }, | |
| - [], | |
| - ); | |
| - | |
| - // once we have a connection id, set it in state | |
| - useEffect(() => { | |
| - subscribe( | |
| - WebsocketWebsocketMessageType.ConnectionInfoResponse, | |
| - handleConnectionInfo, | |
| - ); | |
| - return () => { | |
| - unsubscribe( | |
| - WebsocketWebsocketMessageType.ConnectionInfoResponse, | |
| - handleConnectionInfo, | |
| - ); | |
| - }; | |
| - }, [handleConnectionInfo, subscribe, unsubscribe]); | |
| - | |
| - return ( | |
| - <WebsocketContext.Provider | |
| - value={{ | |
| - readyState, | |
| - subscribe, | |
| - unsubscribe, | |
| - sendMessage, | |
| - emit, | |
| - connectionId, | |
| - }} | |
| - > | |
| - {children} | |
| - </WebsocketContext.Provider> | |
| - ); | |
| -}; | |
| diff --git a/src/context/WebsocketContext/index.ts b/src/context/WebsocketContext/index.ts | |
| deleted file mode 100644 | |
| index ecb82354..00000000 | |
| --- a/src/context/WebsocketContext/index.ts | |
| +++ /dev/null | |
| @@ -1,4 +0,0 @@ | |
| -export { useWebsocketContext, useWebsocketEvent } from "./useWebsocketContext"; | |
| -export { WebsocketContext } from "./WebsocketContext"; | |
| -export type { EventPayload, EventType } from "./WebsocketContext"; | |
| -export { WebsocketProvider } from "./WebsocketProvider"; | |
| diff --git a/src/context/WebsocketContext/useWebsocketContext.tsx b/src/context/WebsocketContext/useWebsocketContext.tsx | |
| deleted file mode 100644 | |
| index 0844362f..00000000 | |
| --- a/src/context/WebsocketContext/useWebsocketContext.tsx | |
| +++ /dev/null | |
| @@ -1,25 +0,0 @@ | |
| -import { useContext, useEffect } from "react"; | |
| -import { WebsocketBroadcastMessagePayload } from "src/phoenix-generated"; | |
| -import { EventType, WebsocketContext } from "./WebsocketContext"; | |
| - | |
| -export const useWebsocketContext = () => { | |
| - const context = useContext(WebsocketContext); | |
| - if (!context) { | |
| - throw new Error( | |
| - "useWebsocketContext must be used within a WebsocketProvider", | |
| - ); | |
| - } | |
| - return context; | |
| -}; | |
| - | |
| -export const useWebsocketEvent = <T extends EventType>( | |
| - eventType: T, | |
| - callback: (payload: WebsocketBroadcastMessagePayload) => void, | |
| -) => { | |
| - const { subscribe, unsubscribe } = useWebsocketContext(); | |
| - | |
| - useEffect(() => { | |
| - subscribe(eventType, callback); | |
| - return () => unsubscribe(eventType, callback); | |
| - }, [eventType, callback, subscribe, unsubscribe]); | |
| -}; | |
| diff --git a/src/hooks/useIdleTimer.tsx b/src/hooks/useIdleTimer.tsx | |
| index 190e9473..9d0ca1a9 100644 | |
| --- a/src/hooks/useIdleTimer.tsx | |
| +++ b/src/hooks/useIdleTimer.tsx | |
| @@ -10,12 +10,6 @@ const useIdleTimer = (onIdle: () => void, idleTime: number) => { | |
| const hasExecutedRef = useRef(false); // To track if the function has been executed | |
| const isIdleRef = useRef(false); | |
| - // Do not depend on onIdle to be stable | |
| - const onIdleRef = useRef(onIdle); | |
| - useEffect(() => { | |
| - onIdleRef.current = onIdle; | |
| - }, [onIdle]); | |
| - | |
| useEffect(() => { | |
| const resetTimer = () => { | |
| clearTimeout(idleTimerRef.current ?? undefined); | |
| @@ -29,7 +23,7 @@ const useIdleTimer = (onIdle: () => void, idleTime: number) => { | |
| isIdleRef.current = true; | |
| if (!hasExecutedRef.current) { | |
| - onIdleRef.current(); // Execute the function | |
| + onIdle(); // Execute the function | |
| hasExecutedRef.current = true; // Mark as executed | |
| } | |
| }, idleTime); | |
| diff --git a/src/hooks/useItemDetailTabs.tsx b/src/hooks/useItemDetailTabs.tsx | |
| index 3fb11e9c..5cc0614e 100644 | |
| --- a/src/hooks/useItemDetailTabs.tsx | |
| +++ b/src/hooks/useItemDetailTabs.tsx | |
| @@ -113,7 +113,6 @@ export const useItemDetailTabs = ( | |
| content: <PurchasedWithTab cohortItemId={entityItem?.cohortItemId} />, | |
| }, | |
| ]; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| allPossibleEntities.length, | |
| entityItem, | |
| diff --git a/src/hooks/useKeypress.tsx b/src/hooks/useKeypress.tsx | |
| index d2c8fe7d..8f7ea565 100644 | |
| --- a/src/hooks/useKeypress.tsx | |
| +++ b/src/hooks/useKeypress.tsx | |
| @@ -47,7 +47,6 @@ export const useKeypress = ( | |
| } | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [mapping], | |
| ); | |
| diff --git a/src/hooks/useMenuConfig.tsx b/src/hooks/useMenuConfig.tsx | |
| index 7ea64ef6..e6f400cd 100644 | |
| --- a/src/hooks/useMenuConfig.tsx | |
| +++ b/src/hooks/useMenuConfig.tsx | |
| @@ -429,7 +429,6 @@ export const useMenuConfig = (): { | |
| ], | |
| }, | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| register.isRegisterOpen, | |
| register.registerNumber, | |
| diff --git a/src/hooks/useOrderItemDecisionUpdater.ts b/src/hooks/useOrderItemDecisionUpdater.ts | |
| deleted file mode 100644 | |
| index b041b7f9..00000000 | |
| --- a/src/hooks/useOrderItemDecisionUpdater.ts | |
| +++ /dev/null | |
| @@ -1,94 +0,0 @@ | |
| -import { useToast } from "components/ui/use-toast"; | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useState } from "react"; | |
| -import { useUpdateOrderItemDecisionStatus } from "src/phoenix-generated"; | |
| -import { typeid } from "typeid-js"; | |
| - | |
| -interface DecisionUpdate { | |
| - decisionId: string; | |
| - status: "ACCEPTED" | "REJECTED"; | |
| - reason?: string; | |
| - userId: string; | |
| - source?: string; | |
| -} | |
| - | |
| -interface UpdaterOptions { | |
| - onSuccess?: () => void; | |
| - onError?: (error: any) => void; | |
| -} | |
| - | |
| -export const useOrderItemDecisionUpdater = (options: UpdaterOptions = {}) => { | |
| - const { toast } = useToast(); | |
| - const [isUpdating, setIsUpdating] = useState(false); | |
| - | |
| - const { mutateAsync: updateOrderItemDecisionStatus } = | |
| - useUpdateOrderItemDecisionStatus({ | |
| - mutation: { | |
| - onSuccess: () => { | |
| - options.onSuccess?.(); | |
| - }, | |
| - onError: (err: any) => { | |
| - const errorMessage = | |
| - err.response?.data?.message || "Failed to update decision"; | |
| - toast({ | |
| - title: "Error", | |
| - description: errorMessage, | |
| - variant: "destructive", | |
| - }); | |
| - captureException(err); | |
| - options.onError?.(err); | |
| - }, | |
| - }, | |
| - }); | |
| - | |
| - const updateDecisions = async (updates: DecisionUpdate[]) => { | |
| - if (updates.length === 0) return; | |
| - | |
| - setIsUpdating(true); | |
| - try { | |
| - await Promise.all( | |
| - updates.map((update) => | |
| - updateOrderItemDecisionStatus({ | |
| - id: update.decisionId, | |
| - data: { | |
| - status: update.status, | |
| - decisionMadeById: update.userId, | |
| - decisionTime: new Date().toISOString(), | |
| - metadata: { | |
| - decisionContext: { | |
| - batchId: typeid("ordibat").toString(), | |
| - source: update.source || "unknown", | |
| - }, | |
| - }, | |
| - // @ts-expect-error - TODO: fix this in generator | |
| - fulfillmentId: null, | |
| - reason: | |
| - update.reason || | |
| - `${update.status.toLowerCase()} via cashier interface`, | |
| - }, | |
| - }), | |
| - ), | |
| - ); | |
| - | |
| - const successMessage = | |
| - updates.length === 1 | |
| - ? `Decisions updated` | |
| - : `${updates.length} item(s) updated. Remember to prepare the accepted items for pickup.`; | |
| - | |
| - toast({ | |
| - title: "Success", | |
| - description: successMessage, | |
| - variant: "success", | |
| - }); | |
| - } catch (error) { | |
| - // Error handling is done in the mutation onError | |
| - } finally { | |
| - setIsUpdating(false); | |
| - } | |
| - }; | |
| - | |
| - return { | |
| - updateDecisions, | |
| - isUpdating, | |
| - }; | |
| -}; | |
| diff --git a/src/hooks/usePostHogFeatureFlag.ts b/src/hooks/usePostHogFeatureFlag.ts | |
| index 2b0629d1..86a2673e 100644 | |
| --- a/src/hooks/usePostHogFeatureFlag.ts | |
| +++ b/src/hooks/usePostHogFeatureFlag.ts | |
| @@ -1,4 +1,3 @@ | |
| -import { useStatsigClient } from "@statsig/react-bindings"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| import { usePostHog } from "posthog-js/react"; | |
| import { useEffect, useState } from "react"; | |
| @@ -8,16 +7,13 @@ export function useFeatureFlagEnabled( | |
| flag: string, | |
| defaultValue: boolean = false, | |
| ): boolean { | |
| - const posthogClient = usePostHog(); | |
| - const { client: statsigClient } = useStatsigClient(); | |
| + const client = usePostHog(); | |
| const [query] = useQueryParam(flag, BooleanParam); | |
| const [featureEnabled, setFeatureEnabled] = useState<boolean | undefined>( | |
| () => { | |
| try { | |
| - return ( | |
| - posthogClient.isFeatureEnabled(flag) || statsigClient.checkGate(flag) | |
| - ); | |
| + return client.isFeatureEnabled(flag); | |
| } catch (error) { | |
| captureException(error); | |
| return defaultValue; | |
| @@ -26,21 +22,17 @@ export function useFeatureFlagEnabled( | |
| ); | |
| useEffect(() => { | |
| - return posthogClient.onFeatureFlags(() => { | |
| + return client.onFeatureFlags(() => { | |
| setFeatureEnabled((prev) => { | |
| try { | |
| - return ( | |
| - posthogClient.isFeatureEnabled(flag) || | |
| - statsigClient.checkGate(flag) | |
| - ); | |
| + return client.isFeatureEnabled(flag); | |
| } catch (error) { | |
| captureException(error); | |
| return prev ?? defaultValue; // Ensure a boolean is always returned | |
| } | |
| }); | |
| }); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| - }, [posthogClient, statsigClient, flag]); | |
| + }, [client, flag]); | |
| const val = query ?? featureEnabled ?? defaultValue; | |
| console.log(`Feature flag "${flag}" is ${val ? "enabled" : "disabled"}.`); | |
| diff --git a/src/hooks/usePrintTransactionTotalsReceipt.tsx b/src/hooks/usePrintTransactionTotalsReceipt.tsx | |
| index dd99ca58..9525fd2a 100644 | |
| --- a/src/hooks/usePrintTransactionTotalsReceipt.tsx | |
| +++ b/src/hooks/usePrintTransactionTotalsReceipt.tsx | |
| @@ -417,7 +417,6 @@ export const usePrintTransactionTotalsReceipt = () => { | |
| </Printer>, | |
| ); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [printerWidth, sendReceiptData, entity.id], | |
| ); | |
| diff --git a/src/hooks/useSalesChannelWizard.ts b/src/hooks/useSalesChannelWizard.ts | |
| deleted file mode 100644 | |
| index 7c34d3d2..00000000 | |
| --- a/src/hooks/useSalesChannelWizard.ts | |
| +++ /dev/null | |
| @@ -1,116 +0,0 @@ | |
| -import { captureException } from "@sentry/react"; | |
| -import { useCallback } from "react"; | |
| -import { useToast } from "src/components/ui/use-toast"; | |
| -import { | |
| - EntitySalesChannel, | |
| - UpsertEntitySalesChannelPaymentMethodDto, | |
| - UpsertSalesChannel, | |
| - useCreateEntitySalesChannelPaymentMethod, | |
| - useUpsertEntitySalesChannel, | |
| -} from "src/spring-generated"; | |
| - | |
| -// Form data type that includes payment methods | |
| -export type SalesChannelFormData = UpsertSalesChannel & { | |
| - paymentMethods: Array< | |
| - UpsertEntitySalesChannelPaymentMethodDto & { isDefault: boolean } | |
| - >; | |
| -}; | |
| - | |
| -interface UseSalesChannelWizardProps { | |
| - onSuccess?: (channel: EntitySalesChannel) => void; | |
| - onClose?: () => void; | |
| -} | |
| - | |
| -export const useSalesChannelWizard = ({ | |
| - onSuccess, | |
| - onClose, | |
| -}: UseSalesChannelWizardProps) => { | |
| - const { toast } = useToast(); | |
| - | |
| - const { mutateAsync: upsertSalesChannel } = useUpsertEntitySalesChannel(); | |
| - const { mutateAsync: createPaymentMethod } = | |
| - useCreateEntitySalesChannelPaymentMethod(); | |
| - | |
| - const handleComplete = useCallback( | |
| - async (data: SalesChannelFormData) => { | |
| - try { | |
| - // Step 1: Create EntitySalesChannel without default payment method | |
| - const salesChannelData: UpsertSalesChannel = { | |
| - ...data, | |
| - defaultPaymentMethodId: undefined, // Will be set later | |
| - }; | |
| - | |
| - const createdSalesChannel = await upsertSalesChannel({ | |
| - data: salesChannelData, | |
| - }); | |
| - | |
| - // Step 2: Create all payment methods | |
| - const paymentMethodPromises = data.paymentMethods.map( | |
| - async (method) => { | |
| - const paymentMethodData: UpsertEntitySalesChannelPaymentMethodDto = | |
| - { | |
| - entityId: data.entityId, | |
| - entitySalesChannelId: createdSalesChannel.id, | |
| - paymentMethodType: method.paymentMethodType, | |
| - cohortPriceLevelId: method.cohortPriceLevelId, | |
| - displayOnPayButton: method.displayOnPayButton, | |
| - isArchived: false, | |
| - }; | |
| - | |
| - return await createPaymentMethod({ | |
| - data: paymentMethodData, | |
| - }); | |
| - }, | |
| - ); | |
| - | |
| - const createdPaymentMethods = await Promise.all(paymentMethodPromises); | |
| - | |
| - // Step 3: Find default payment method and update sales channel | |
| - const defaultPaymentMethodIndex = data.paymentMethods.findIndex( | |
| - (pm) => pm.isDefault, | |
| - ); | |
| - const defaultPaymentMethod = | |
| - createdPaymentMethods[defaultPaymentMethodIndex]; | |
| - | |
| - if (defaultPaymentMethod?.id) { | |
| - await upsertSalesChannel({ | |
| - data: { | |
| - ...salesChannelData, | |
| - id: createdSalesChannel.id, | |
| - defaultPaymentMethodId: defaultPaymentMethod.id, | |
| - priceLevelId: defaultPaymentMethod.cohortPriceLevelId, | |
| - }, | |
| - }); | |
| - } | |
| - | |
| - toast({ | |
| - title: "Sales channel created", | |
| - description: "Your sales channel has been created successfully", | |
| - }); | |
| - | |
| - onSuccess?.(createdSalesChannel); | |
| - onClose?.(); | |
| - } catch (error) { | |
| - captureException(error, { | |
| - tags: { component: "SalesChannelWizard" }, | |
| - level: "error", | |
| - }); | |
| - | |
| - toast({ | |
| - variant: "destructive", | |
| - title: "Error creating sales channel", | |
| - description: | |
| - error instanceof Error | |
| - ? error.message | |
| - : "An unexpected error occurred", | |
| - }); | |
| - throw error; | |
| - } | |
| - }, | |
| - [upsertSalesChannel, createPaymentMethod, toast, onSuccess, onClose], | |
| - ); | |
| - | |
| - return { | |
| - handleComplete, | |
| - }; | |
| -}; | |
| diff --git a/src/hooks/useStorefrontDecisionHandler.tsx b/src/hooks/useStorefrontDecisionHandler.tsx | |
| deleted file mode 100644 | |
| index c55e5e2c..00000000 | |
| --- a/src/hooks/useStorefrontDecisionHandler.tsx | |
| +++ /dev/null | |
| @@ -1,65 +0,0 @@ | |
| -import { useEntity } from "context/EntityProvider"; | |
| -import { | |
| - useWebsocketContext, | |
| - useWebsocketEvent, | |
| -} from "context/WebsocketContext"; | |
| -import { useEffect, useState } from "react"; | |
| -import { ReadyState } from "react-use-websocket"; | |
| -import { | |
| - createWebsocketConnection, | |
| - removeWebsocketConnection, | |
| - WebsocketBroadcastMessagePayload, | |
| - WebsocketWebsocketMessageType, | |
| -} from "src/phoenix-generated"; | |
| -import { useIsMounted } from "usehooks-ts"; | |
| - | |
| -/** | |
| - * @param enabled - whether to enable the handler | |
| - * @param onDecision - callback to handle the decision. Make stable reference to avoid re-renders. | |
| - */ | |
| -export const useStorefrontDecisionHandler = ( | |
| - enabled: boolean, | |
| - onDecision: (payload: WebsocketBroadcastMessagePayload) => void, | |
| -) => { | |
| - const { connectionId, readyState } = useWebsocketContext(); | |
| - const [entity] = useEntity(); | |
| - const [wsConnectionId, setWsConnectionId] = useState<number | null>(null); | |
| - | |
| - const mounted = useIsMounted(); | |
| - | |
| - useEffect(() => { | |
| - if ( | |
| - enabled && | |
| - connectionId && | |
| - readyState === ReadyState.OPEN && | |
| - !wsConnectionId && | |
| - entity?.id | |
| - ) { | |
| - console.log("Creating websocket connection"); | |
| - void createWebsocketConnection({ | |
| - connectionId, | |
| - topic: WebsocketWebsocketMessageType.OrderItemDecision, | |
| - entityId: entity?.id, | |
| - }).then((res) => { | |
| - if (mounted()) { | |
| - setWsConnectionId(res.id); | |
| - } | |
| - }); | |
| - } | |
| - return () => { | |
| - if (connectionId && wsConnectionId) { | |
| - if (mounted()) { | |
| - console.log("Removing websocket connection", connectionId); | |
| - void removeWebsocketConnection(connectionId).then(() => { | |
| - setWsConnectionId(null); | |
| - }); | |
| - } | |
| - } | |
| - }; | |
| - }, [connectionId, readyState, entity?.id, enabled, wsConnectionId, mounted]); | |
| - | |
| - useWebsocketEvent( | |
| - WebsocketWebsocketMessageType.OrderItemDecision, | |
| - onDecision, | |
| - ); | |
| -}; | |
| diff --git a/src/index.tsx b/src/index.tsx | |
| index 2367ecfd..b22418d9 100644 | |
| --- a/src/index.tsx | |
| +++ b/src/index.tsx | |
| @@ -7,12 +7,9 @@ import { theme } from "./theme"; | |
| // 2. Update the breakpoints as key-value pairs | |
| -import { StatsigProvider, useClientAsyncInit } from "@statsig/react-bindings"; | |
| -import { StatsigSessionReplayPlugin } from "@statsig/session-replay"; | |
| -import { StatsigAutoCapturePlugin } from "@statsig/web-analytics"; | |
| import { PostHogConfig } from "posthog-js"; | |
| import { PostHogProvider } from "posthog-js/react"; | |
| -import { ReactNode, useEffect } from "react"; | |
| +import { ReactNode, StrictMode, useEffect } from "react"; | |
| import { | |
| createRoutesFromChildren, | |
| matchRoutes, | |
| @@ -27,10 +24,13 @@ import { | |
| } from "./config/sentry/TransformitySentry"; | |
| // Import the dev tools and initialize them | |
| -import Loading from "components/Loading"; | |
| import { Toaster } from "components/ui/toaster"; | |
| import { SentryErrorBoundary } from "config/sentry/SentryErrorBoundary"; | |
| +import { TempoDevtools } from "tempo-devtools"; | |
| import { isIOS } from "utils/deviceUtils"; | |
| +if (import.meta.env.VITE_TEMPO) { | |
| + TempoDevtools.init(); | |
| +} | |
| console.log("NODE_ENV", import.meta.env.NODE_ENV); | |
| console.log("NODE_ENV PROD", import.meta.env.PROD); | |
| @@ -73,6 +73,8 @@ sentryInit({ | |
| tracePropagationTargets: [/^https:\/\/api.transformity\.tech\//], | |
| }), | |
| replayIntegration({ | |
| + sessionSampleRate: 0, | |
| + errorSampleRate: 1.0, | |
| maskAllText: false, | |
| maskAllInputs: false, | |
| networkDetailAllowUrls: [ | |
| @@ -98,7 +100,7 @@ sentryInit({ | |
| // Performance Monitoring | |
| tracesSampleRate: 1.0, // Capture 100% of the transactions | |
| // Session Replay | |
| - replaysSessionSampleRate: 0.0, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. | |
| + replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. | |
| replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. | |
| enabled: import.meta.env.PROD && !isIOS(), | |
| }); | |
| @@ -118,11 +120,6 @@ const PostHogProviderWrapper = ({ children }: { children: ReactNode }) => { | |
| disable_session_recording: !isProd, // Only in production | |
| enable_recording_console_log: isProd, // Only in production | |
| capture_performance: isProd, // Only in production | |
| - bootstrap: { | |
| - featureFlags: { | |
| - offline_mode_data_sync: false, | |
| - }, | |
| - }, | |
| session_recording: { | |
| recordHeaders: true, | |
| recordBody: true, | |
| @@ -143,44 +140,12 @@ const PostHogProviderWrapper = ({ children }: { children: ReactNode }) => { | |
| ); | |
| }; | |
| -const StatsigProviderWrapper = ({ children }: { children: ReactNode }) => { | |
| - const isProd = import.meta.env.PROD; | |
| - const { client } = useClientAsyncInit( | |
| - import.meta.env.VITE_APP_PUBLIC_STATSIG_CLIENT_KEY, | |
| - { userID: undefined }, | |
| - { | |
| - plugins: [ | |
| - new StatsigSessionReplayPlugin({ | |
| - rrwebConfig: { | |
| - maskAllInputs: false, | |
| - maskInputOptions: { | |
| - password: true, | |
| - }, | |
| - }, | |
| - }), | |
| - new StatsigAutoCapturePlugin({ | |
| - consoleLogAutoCaptureSettings: { | |
| - enabled: false, | |
| - }, | |
| - }), | |
| - ], | |
| - environment: { tier: isProd ? "production" : "development" }, | |
| - }, | |
| - ); | |
| - | |
| - return ( | |
| - <StatsigProvider client={client} loadingComponent={<Loading />}> | |
| - {children} | |
| - </StatsigProvider> | |
| - ); | |
| -}; | |
| - | |
| root.render( | |
| - <ChakraProvider | |
| - toastOptions={{ defaultOptions: { position: "top" } }} | |
| - theme={theme} | |
| - > | |
| - <StatsigProviderWrapper> | |
| + <StrictMode> | |
| + <ChakraProvider | |
| + toastOptions={{ defaultOptions: { position: "top" } }} | |
| + theme={theme} | |
| + > | |
| <PostHogProviderWrapper> | |
| <SentryErrorBoundary> | |
| <App /> | |
| @@ -188,6 +153,6 @@ root.render( | |
| <SonnerToaster /> | |
| </SentryErrorBoundary> | |
| </PostHogProviderWrapper> | |
| - </StatsigProviderWrapper> | |
| - </ChakraProvider>, | |
| + </ChakraProvider> | |
| + </StrictMode>, | |
| ); | |
| diff --git a/src/pages/Auth/AuthorizationGuard.tsx b/src/pages/Auth/AuthorizationGuard.tsx | |
| index 31291dd8..6e625d03 100644 | |
| --- a/src/pages/Auth/AuthorizationGuard.tsx | |
| +++ b/src/pages/Auth/AuthorizationGuard.tsx | |
| @@ -12,8 +12,6 @@ import { EmployeeOverrideHandlerProvider } from "context/AuthorizationContext/Em | |
| import { useAuthorization } from "context/AuthorizationContext/useAuthorizationContext"; | |
| import { useEntity } from "context/EntityProvider"; | |
| import { PermissionsProvider } from "context/PermissionsContext"; | |
| -import { StorefrontProvider } from "context/StorefrontContext/StorefrontProvider"; | |
| -import { WebsocketProvider } from "context/WebsocketContext"; | |
| import { EntityConfigKey } from "generated/types"; | |
| import { useEntityConfig } from "hooks/useEntityConfig"; | |
| import { usePostHog } from "posthog-js/react"; | |
| @@ -21,7 +19,6 @@ import { useEffect, useRef } from "react"; | |
| import { Outlet, useNavigate } from "react-router-dom"; | |
| import { SelectStoreForm } from "../../components/Auth/AuthorizationFlowForms/SelectStoreForm"; | |
| import Loading from "../../components/Loading"; | |
| -import { SubscriptionBannerWrapper } from "../../components/SubscriptionBannerWrapper"; | |
| import { CenteredLayout } from "../../components/layouts/CenteredLayout"; | |
| import { useIdleTime } from "../../hooks/useIdleTime"; | |
| import { EmployeePinLoginCard } from "./EmployeePinLoginCard"; | |
| @@ -95,16 +92,11 @@ const AuthorizationGuard: React.FC<AuthorizationFlowProps> = () => { | |
| if (entity && !isStoreLogin && user && permissions) { | |
| return ( | |
| <PermissionsProvider permissions={permissions}> | |
| - <WebsocketProvider> | |
| - <EmployeeOverrideHandlerProvider> | |
| - <RemoteAccessGuard> | |
| - <StorefrontProvider> | |
| - <SubscriptionBannerWrapper /> | |
| - <Outlet /> | |
| - </StorefrontProvider> | |
| - </RemoteAccessGuard> | |
| - </EmployeeOverrideHandlerProvider> | |
| - </WebsocketProvider> | |
| + <EmployeeOverrideHandlerProvider> | |
| + <RemoteAccessGuard> | |
| + <Outlet /> | |
| + </RemoteAccessGuard> | |
| + </EmployeeOverrideHandlerProvider> | |
| </PermissionsProvider> | |
| ); | |
| } | |
| diff --git a/src/pages/Auth/SignIn.tsx b/src/pages/Auth/SignIn.tsx | |
| index 40b03ab4..62f0fa8c 100644 | |
| --- a/src/pages/Auth/SignIn.tsx | |
| +++ b/src/pages/Auth/SignIn.tsx | |
| @@ -35,7 +35,7 @@ const SignIn = () => { | |
| const handleGoogleSignIn = async () => { | |
| setError(""); | |
| try { | |
| - await googleSignIn(); | |
| + await googleSignIn!(); | |
| } catch (e: any) { | |
| if (e.message.includes("(auth/popup-closed-by-user)")) { | |
| setError("Sign In with Google Canceled"); | |
| @@ -47,7 +47,7 @@ const SignIn = () => { | |
| const handleForgotPassword = async (email: string) => { | |
| try { | |
| - await triggerResetEmail(email); | |
| + await triggerResetEmail!(email); | |
| setError("A password reset link has been sent to your email address."); | |
| } catch (e: any) { | |
| setError(e.message); | |
| diff --git a/src/pages/CannyFeedback.tsx b/src/pages/CannyFeedback.tsx | |
| index d72ba993..8ea3ab1c 100644 | |
| --- a/src/pages/CannyFeedback.tsx | |
| +++ b/src/pages/CannyFeedback.tsx | |
| @@ -1,7 +1,11 @@ | |
| + | |
| + | |
| // @ts-nocheck | |
| +import { CommandMenuShortcutOverlay } from "components/common/CommandMenuShortcutOverlay"; | |
| +import { useCannyApi } from "config/ItemsApi"; | |
| import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| -import { useEffect } from "react"; | |
| +import { useEffect, useState } from "react"; | |
| import { NavBarPlain } from "../components/navbar/NavBarPlain"; | |
| import { useGetCannySsoToken } from "../generated/hooks/useGetCannySsoToken"; | |
| @@ -59,6 +63,7 @@ const Feedback = () => { | |
| className="h-full overflow-y-auto" | |
| > | |
| <div data-canny /> | |
| + <CommandMenuShortcutOverlay withOverlay={true} /> | |
| </div> | |
| </> | |
| ); | |
| diff --git a/src/pages/RegisterOpeningPage.tsx b/src/pages/RegisterOpeningPage.tsx | |
| index d4230d9c..472de5a7 100644 | |
| --- a/src/pages/RegisterOpeningPage.tsx | |
| +++ b/src/pages/RegisterOpeningPage.tsx | |
| @@ -15,7 +15,7 @@ import { | |
| useToast, | |
| } from "@chakra-ui/react"; | |
| import { captureException } from "@sentry/react"; | |
| -import type { DrawerReportingFormValues } from "components/DrawerReporting/DrawerReporting"; | |
| +import { DrawerReportingFormValues } from "components/DrawerReporting/DrawerReporting"; | |
| import { DrawerReportingModal } from "components/DrawerReporting/DrawerReportingModal"; | |
| import ChangeRegisterForm from "components/register/ChangeRegisterForm"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| @@ -26,7 +26,7 @@ import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| import { useEntityConfig } from "hooks/useEntityConfig"; | |
| import posthog from "posthog-js"; | |
| import { useCallback, useEffect, useState } from "react"; | |
| -import { Link, Navigate, useNavigate } from "react-router-dom"; | |
| +import { Link, useNavigate } from "react-router-dom"; | |
| import { | |
| useCreateDrawerCountSettlement, | |
| useGetCurrentOpenDrawerSettlement, | |
| @@ -122,113 +122,119 @@ const RegisterOpeningPage = () => { | |
| }, | |
| }); | |
| - if (isRegisterOpen.isRegisterOpen) { | |
| - return <Navigate to="/sale/" replace />; | |
| - } | |
| - | |
| return ( | |
| - <Stack | |
| - background={"gray.100"} | |
| - display={"flex"} | |
| - justify="flex-start" | |
| - align="center" | |
| - spacing="10px" | |
| - overflow="hidden" | |
| - width="100vw" | |
| - height="100vh" | |
| - maxWidth="100%" | |
| - maxHeight={"100%"} | |
| - overflowY={"auto"} | |
| - > | |
| - <NavBarPlain hideSalesScreenShortcut /> | |
| - <DrawerReportingModal | |
| - {...drawerCountingModalDisclosure} | |
| - isPending={isPending} | |
| - headerTitle="Opening Drawer Count" | |
| - submitBtnText="Start Shift" | |
| - registerNumber={registerValue.registerNumber} | |
| - onSubmit={async (data: DrawerReportingFormValues) => { | |
| - await submitOpeningDrawerCount({ | |
| - registerId: registerValue.registerNumber, | |
| - data, | |
| - }); | |
| - }} | |
| - /> | |
| - | |
| - <Card paddingX={"10px"} pb={3} height="auto"> | |
| - <CardHeader> | |
| - <Heading size="lg">Select Workstation</Heading> | |
| - </CardHeader> | |
| - <Flex direction={"column"} gap={"3"}> | |
| - <FormControl> | |
| - <Select | |
| - name="register" | |
| - value={registerValue.registerNumber} | |
| - isDisabled={!hasPermission("register/*:change")} | |
| - onChange={(e) => { | |
| - const value = e.currentTarget.value; | |
| - | |
| - if (!value) { | |
| - return; | |
| - } | |
| - return setRegisterValue((prev) => { | |
| - posthog.capture("register_opening_page_select_register", { | |
| - old_register: prev.registerNumber, | |
| - new_register: +value, | |
| - }); | |
| - if (prev.registerNumber !== +value) { | |
| - posthog.capture("register_opening_page_register_switched", { | |
| - old_register: prev.registerNumber, | |
| - new_register: +value, | |
| + <> | |
| + <Stack | |
| + background={"gray.100"} | |
| + display={"flex"} | |
| + justify="flex-start" | |
| + align="center" | |
| + spacing="10px" | |
| + overflow="hidden" | |
| + width="100vw" | |
| + height="100vh" | |
| + maxWidth="100%" | |
| + maxHeight={"100%"} | |
| + overflowY={"auto"} | |
| + > | |
| + <NavBarPlain hideSalesScreenShortcut /> | |
| + <DrawerReportingModal | |
| + {...drawerCountingModalDisclosure} | |
| + isPending={isPending} | |
| + headerTitle="Opening Drawer Count" | |
| + submitBtnText="Start Shift" | |
| + registerNumber={registerValue.registerNumber} | |
| + onSubmit={async (data: DrawerReportingFormValues) => { | |
| + await submitOpeningDrawerCount({ | |
| + registerId: registerValue.registerNumber, | |
| + data, | |
| + }); | |
| + }} | |
| + /> | |
| + | |
| + <Card paddingX={"10px"} pb={3} height="auto"> | |
| + <CardHeader> | |
| + <Heading size="lg">Select Workstation</Heading> | |
| + </CardHeader> | |
| + <Flex direction={"column"} gap={"3"}> | |
| + <> | |
| + <FormControl> | |
| + <Select | |
| + name="register" | |
| + value={registerValue.registerNumber} | |
| + isDisabled={!hasPermission("register/*:change")} | |
| + onChange={(e) => { | |
| + const value = e.currentTarget.value; | |
| + | |
| + if (!value) { | |
| + return; | |
| + } | |
| + return setRegisterValue((prev) => { | |
| + posthog.capture("register_opening_page_select_register", { | |
| + old_register: prev.registerNumber, | |
| + new_register: +value, | |
| + }); | |
| + if (prev.registerNumber !== +value) { | |
| + posthog.capture( | |
| + "register_opening_page_register_switched", | |
| + { | |
| + old_register: prev.registerNumber, | |
| + new_register: +value, | |
| + }, | |
| + ); | |
| + } | |
| + return { ...prev, registerNumber: +value }; | |
| }); | |
| - } | |
| - return { ...prev, registerNumber: +value }; | |
| - }); | |
| + }} | |
| + > | |
| + {entity.registers | |
| + .sort((a, b) => a.registerId - b.registerId) | |
| + .map((register) => ( | |
| + <option | |
| + value={register.registerId} | |
| + key={register.registerId} | |
| + > | |
| + Register: {register.registerId} | |
| + </option> | |
| + ))} | |
| + </Select> | |
| + </FormControl> | |
| + </> | |
| + <ChangeRegisterForm | |
| + onSubmit={async () => { | |
| + if (!!currentOpenDrawerSettlement) { | |
| + updateRegisterStateAndOpen(); | |
| + } else if (enableDrawerCounting.value) { | |
| + drawerCountingModalDisclosureOnOpen(); | |
| + } else { | |
| + await submitOpeningDrawerCount({ | |
| + registerId: registerValue.registerNumber, | |
| + data: {}, | |
| + }); | |
| + } | |
| }} | |
| - > | |
| - {entity.registers | |
| - .sort((a, b) => a.registerId - b.registerId) | |
| - .map((register) => ( | |
| - <option value={register.registerId} key={register.registerId}> | |
| - Register: {register.registerId} | |
| - </option> | |
| - ))} | |
| - </Select> | |
| - </FormControl> | |
| - <ChangeRegisterForm | |
| - onSubmit={async () => { | |
| - if (currentOpenDrawerSettlement) { | |
| - updateRegisterStateAndOpen(); | |
| - } else if (enableDrawerCounting.value) { | |
| - drawerCountingModalDisclosureOnOpen(); | |
| - } else { | |
| - await submitOpeningDrawerCount({ | |
| - registerId: registerValue.registerNumber, | |
| - data: {}, | |
| - }); | |
| - } | |
| - }} | |
| - disabled={isPending || isFetching} | |
| - selectedRegister={registerValue.registerNumber} | |
| - /> | |
| - <Divider orientation="horizontal" /> | |
| - <Center> | |
| - <Text>OR</Text> | |
| - </Center> | |
| - <Divider orientation="horizontal" /> | |
| - <ChakraLink as={Link} to="/items/search/"> | |
| - <Button | |
| - type="submit" | |
| - colorScheme="blue" | |
| - isDisabled={isPending} | |
| - w="100%" | |
| - > | |
| - Back Office | |
| - </Button> | |
| - </ChakraLink> | |
| - </Flex> | |
| - </Card> | |
| - </Stack> | |
| + disabled={isPending || isFetching} | |
| + selectedRegister={registerValue.registerNumber} | |
| + /> | |
| + <Divider orientation="horizontal" /> | |
| + <Center> | |
| + <Text>OR</Text> | |
| + </Center> | |
| + <Divider orientation="horizontal" /> | |
| + <ChakraLink as={Link} to="/items/search/"> | |
| + <Button | |
| + type="submit" | |
| + colorScheme="blue" | |
| + isDisabled={isPending} | |
| + w="100%" | |
| + > | |
| + Back Office | |
| + </Button> | |
| + </ChakraLink> | |
| + </Flex> | |
| + </Card> | |
| + </Stack> | |
| + </> | |
| ); | |
| }; | |
| diff --git a/src/pages/SalePage/SalePage.tsx b/src/pages/SalePage/SalePage.tsx | |
| index e4e7837f..35d3152c 100644 | |
| --- a/src/pages/SalePage/SalePage.tsx | |
| +++ b/src/pages/SalePage/SalePage.tsx | |
| @@ -11,6 +11,7 @@ import { useEntitySelected } from "context/EntityProvider"; | |
| import { useRegisterProvider } from "context/RegisterProvider"; | |
| import { SalesContextType, useSalesContext } from "context/Sales/SalesContext"; | |
| import { useEffect, useMemo, useRef } from "react"; | |
| +import usePoleDisplay from "../../components/PoleDisplay"; | |
| import { QtyHotKeys } from "../../components/QtyHotKeys"; | |
| import { BottomLine } from "../../components/SalesScreenComponents/BottomLine/BottomLine"; | |
| import { ItemNotInSystemAlert } from "../../components/SalesScreenComponents/Modals/ItemNotInSystemAlert"; | |
| @@ -20,15 +21,9 @@ import { QuickPicks } from "../../components/SalesScreenComponents/SalesButtonGr | |
| import { SalesScreenItemsTable } from "../../components/SalesScreenComponents/SalesScreenItemsTable"; | |
| import SaleScreenNavBar from "../../components/navbar/SaleScreenNavBar"; | |
| -import { usePGlite } from "@electric-sql/pglite-react"; | |
| -import { SalePageSyncOverlay } from "components/SalePageSyncOverlay"; | |
| import { VariablePriceModal } from "components/SalesScreenComponents/Modals/VariablePriceModal"; | |
| import { useSalePageConfig } from "components/SalesScreenComponents/SalePageConfigProvider"; | |
| import { TotalSummaryCard } from "components/SalesScreenComponents/TotalSummaryCard"; | |
| -import { | |
| - RetrieveItemsByUpc, | |
| - RetrieveItemsByUpcQuery, | |
| -} from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { ComboboxSelectRef } from "components/ui/ComboboxSelect"; | |
| import { usePermissions } from "context/PermissionsContext"; | |
| import { | |
| @@ -40,10 +35,11 @@ import useIdleTimer from "hooks/useIdleTimer"; | |
| import { Navigate } from "react-router-dom"; | |
| import { BottomLineRight } from "src/components/SalesScreenComponents/BottomLine/BottomLineRight"; | |
| import { SaleStep } from "src/components/SalesScreenComponents/Modals/ReviewSaleModal/ReviewSaleModal"; | |
| -import { TransactionPaymentForm } from "src/generated/types"; | |
| +import { EntityItemDetail } from "src/generated"; | |
| import { EntityConfigKey } from "src/generated/types/EntityConfigKey"; | |
| import { useEntityConfig } from "src/hooks/useEntityConfig"; | |
| import { useGetAllDepartmentsForEntity } from "src/hooks/useGetAllDepartmentsForEntity"; | |
| +import { USDollar } from "src/utils/dollarFormat"; | |
| import Loading from "../../components/Loading"; | |
| import { useKeypress } from "../../hooks/useKeypress"; | |
| import { playFailureSound, playStopSound } from "../../utils/audioUtils"; | |
| @@ -69,7 +65,6 @@ const SalePage = () => { | |
| transactionTotalPrice, | |
| clearCart, | |
| taxExempt, | |
| - discount, | |
| governmentID, | |
| setGovernmentID, | |
| customer, | |
| @@ -78,15 +73,8 @@ const SalePage = () => { | |
| setTransactionId, | |
| isCalculatingCartPrice, | |
| isGetCartPricingError, | |
| - calculateCartPrice, | |
| - paymentMethodTypeToPaymentMethod, | |
| - calculateMethodsWithPrices, | |
| - findBestPaymentMethod, | |
| - isCalculatingBackgroundPaymentMethodTotals, | |
| - setSkipSetItemsInCart, | |
| } = useSalesContext(); | |
| - const { selectedSalesChannel, overriddenCohortPriceLevel } = | |
| - useSalePageConfig(); | |
| + const { selectedSalesChannel } = useSalePageConfig(); | |
| const { value: payAfterConfirm } = useEntityConfig( | |
| EntityConfigKey.PAY_AFTER_CONFIRM, | |
| false, | |
| @@ -97,49 +85,29 @@ const SalePage = () => { | |
| if (!departmentMap) return <Loading />; | |
| return ( | |
| - <SalePageSyncOverlay> | |
| - <SalesPaymentProvider | |
| - salePaymentType="sale" | |
| - isGetCartPricingError={isGetCartPricingError} | |
| - isCalculatingCartPrice={isCalculatingCartPrice} | |
| - key={payAfterConfirm ? "pay-after-confirm" : "pay-before-confirm"} | |
| - salesChannel={selectedSalesChannel} | |
| - overriddenCohortPriceLevel={overriddenCohortPriceLevel} | |
| - transactionId={transactionId} | |
| - setTransactionId={setTransactionId} | |
| - transactionItems={convertToTransactionItems( | |
| - itemDetails, | |
| - taxExempt, | |
| - departmentMap, | |
| - )} | |
| - transactionTotalPrice={transactionTotalPrice} | |
| - clearCart={clearCart} | |
| - governmentID={governmentID} | |
| - setGovernmentID={setGovernmentID} | |
| - customer={customer} | |
| - resetCartToCurrentItems={resetCartToCurrentItems} | |
| - payAfterConfirm={payAfterConfirm} | |
| - calculateCartPrice={async (paymentMethodId?: string) => | |
| - await calculateCartPrice({ | |
| - requestedItems: itemDetails, | |
| - requestTaxExempt: taxExempt, | |
| - requestedCustomer: customer, | |
| - requestedDiscount: discount, | |
| - paymentMethodId: paymentMethodId, | |
| - }) | |
| - } | |
| - paymentMethodTypeToPaymentMethod={paymentMethodTypeToPaymentMethod} | |
| - calculateMethodsWithPrices={calculateMethodsWithPrices} | |
| - findBestPaymentMethod={findBestPaymentMethod} | |
| - isCalculatingBackgroundPaymentMethodTotals={ | |
| - isCalculatingBackgroundPaymentMethodTotals | |
| - } | |
| - selectedSalesChannel={selectedSalesChannel} | |
| - setSkipSetItemsInCart={setSkipSetItemsInCart} | |
| - > | |
| - <SalePageInner /> | |
| - </SalesPaymentProvider> | |
| - </SalePageSyncOverlay> | |
| + <SalesPaymentProvider | |
| + salePaymentType="sale" | |
| + isGetCartPricingError={isGetCartPricingError} | |
| + isCalculatingCartPrice={isCalculatingCartPrice} | |
| + key={payAfterConfirm ? "pay-after-confirm" : "pay-before-confirm"} | |
| + salesChannel={selectedSalesChannel} | |
| + transactionId={transactionId} | |
| + setTransactionId={setTransactionId} | |
| + transactionItems={convertToTransactionItems( | |
| + itemDetails, | |
| + taxExempt, | |
| + departmentMap, | |
| + )} | |
| + transactionTotalPrice={transactionTotalPrice} | |
| + clearCart={clearCart} | |
| + governmentID={governmentID} | |
| + setGovernmentID={setGovernmentID} | |
| + customer={customer} | |
| + resetCartToCurrentItems={resetCartToCurrentItems} | |
| + payAfterConfirm={payAfterConfirm} | |
| + > | |
| + <SalePageInner /> | |
| + </SalesPaymentProvider> | |
| ); | |
| }; | |
| @@ -159,9 +127,7 @@ export const SalePageInner = () => { | |
| taxExempt, | |
| customer, | |
| discount, | |
| - paymentMethodTypeToPaymentMethod, | |
| } = useSalesContext(); | |
| - const db = usePGlite(); | |
| const { | |
| lastChangeDue, | |
| payWithCashModal, | |
| @@ -200,6 +166,7 @@ export const SalePageInner = () => { | |
| }); | |
| const [entity, , isEntityLoading] = useEntitySelected(); | |
| const { register } = useRegisterProvider(); | |
| + const poleDisplay = usePoleDisplay(); | |
| const { hasPermission } = usePermissions(); | |
| const { value: barcodeExactMatch } = useEntityConfig( | |
| EntityConfigKey.EXACT_BARCODE_LOOKUP, | |
| @@ -365,7 +332,7 @@ export const SalePageInner = () => { | |
| qRegex, | |
| (_?: KeyboardEvent) => { | |
| if (barCodeScannerInput) { | |
| - setQuantity(parseInt(barCodeScannerInput.join(""), 10)); | |
| + setQuantity(parseInt(barCodeScannerInput.join(""))); | |
| barCodeScannerInput = undefined; | |
| } | |
| }, | |
| @@ -436,19 +403,9 @@ export const SalePageInner = () => { | |
| if (saleStep === SaleStep.Payment) { | |
| barCodeScannerInput = undefined; | |
| if (itemDetails.size && transactionTotalPrice() > 0) { | |
| - // Check if there are multiple credit card methods | |
| - const creditCardMethods = | |
| - paymentMethodTypeToPaymentMethod[ | |
| - TransactionPaymentForm["CREDIT CARD"] | |
| - ] || []; | |
| - | |
| - // Only allow F8 if there's one or no credit card methods | |
| - if (creditCardMethods.length <= 1) { | |
| - creditCardPaid(undefined, creditCardMethods[0]?.id); | |
| - creditCardModalV2.onOpen(); | |
| - reviewTransactionModal.onClose(); | |
| - } | |
| - // If there are multiple methods, F8 is disabled (do nothing) | |
| + creditCardPaid(); | |
| + creditCardModalV2.onOpen(); | |
| + reviewTransactionModal.onClose(); | |
| } | |
| } | |
| }, | |
| @@ -488,6 +445,12 @@ export const SalePageInner = () => { | |
| barCodeScannerInput = undefined; | |
| }, 1000); | |
| + // Update the pole display when the last change due is updated. | |
| + useEffect(() => { | |
| + if (lastChangeDue === undefined) return; | |
| + void poleDisplay("Change Due:", `${USDollar.format(lastChangeDue)}`); | |
| + }, [lastChangeDue, poleDisplay]); | |
| + | |
| if (isEntityLoading) return <Loading />; | |
| if (!register.isRegisterOpen) { | |
| @@ -510,20 +473,10 @@ export const SalePageInner = () => { | |
| > | |
| <SaleScreenNavBar | |
| ref={searchBoxRef} | |
| - onSearchSelected={async (entityItem) => { | |
| - if (!entityItem) return; | |
| + onSearchSelected={(itemSelected) => { | |
| + if (!itemSelected) return; | |
| if (!hasPermission("pos/*:add-from-search")) return; | |
| - const options = RetrieveItemsByUpcQuery(entity.id, null, [ | |
| - entityItem.id, | |
| - ]); | |
| - const eRes = await db.query<RetrieveItemsByUpc>( | |
| - options.query, | |
| - options.params, | |
| - ); | |
| - const eItem = eRes.rows?.[0]; | |
| - if (eItem) { | |
| - addSingleItemToCart(eItem, quantity); | |
| - } | |
| + addSingleItemToCart(itemSelected as EntityItemDetail, quantity); | |
| }} | |
| /> | |
| <Stack direction={"row"} px={5} flex={2}> | |
| diff --git a/src/pages/SalePage/SalePageUtils.tsx b/src/pages/SalePage/SalePageUtils.tsx | |
| index 226362c2..dbba7d59 100644 | |
| --- a/src/pages/SalePage/SalePageUtils.tsx | |
| +++ b/src/pages/SalePage/SalePageUtils.tsx | |
| @@ -1,4 +1,3 @@ | |
| -import { RetrieveItemsByUpc } from "components/pg-lite/queries/RetrieveItemsByUpc"; | |
| import { | |
| CalculationMetadata, | |
| CartDiscountType, | |
| @@ -13,7 +12,7 @@ import { | |
| import { Department } from "src/spring-generated"; | |
| export type LineItem = DraftTransactionItemInput & { | |
| id: TransactionItemId; | |
| - item?: RetrieveItemsByUpc; | |
| + item?: EntityItemDetail; | |
| /** Discount requested on this line item. */ | |
| lineItemDiscount?: Discount; | |
| subtotal: number; | |
| @@ -33,22 +32,22 @@ export const toPercentage = (price: number, discount?: Discount): number => { | |
| }; | |
| export function addSingleItem( | |
| - retrievedItem: RetrieveItemsByUpc, | |
| + retrievedItem: EntityItemDetail, | |
| transactionId: number, | |
| quantity = 1, | |
| taxExempt = false, | |
| priceAtCost: boolean = false, | |
| ): Omit<LineItem, "id"> & { id?: number } { | |
| const lineItem: Omit<LineItem, "id"> & { id?: number } = { | |
| - itemId: retrievedItem.ei_id, | |
| + itemId: retrievedItem.id, | |
| transactionId: transactionId, | |
| - price: +(priceAtCost | |
| - ? (retrievedItem.ei_cost ?? retrievedItem.ei_price) | |
| - : retrievedItem.ei_price), | |
| + price: priceAtCost | |
| + ? (retrievedItem.cost ?? retrievedItem.price) | |
| + : retrievedItem.price, | |
| item: retrievedItem, | |
| - name: retrievedItem.ci_name, | |
| - originalPrice: +retrievedItem.ei_price, | |
| - department: retrievedItem.ci_department, | |
| + name: retrievedItem.cohortItem.name, | |
| + originalPrice: retrievedItem.price, | |
| + department: retrievedItem.cohortItem.department.id, | |
| quantity: 0, | |
| tax: 0, | |
| taxRate: 0, | |
| diff --git a/src/pages/Settings/AboutStore/AboutStorePanel.tsx b/src/pages/Settings/AboutStore/AboutStorePanel.tsx | |
| index 8a5449a3..c560634c 100644 | |
| --- a/src/pages/Settings/AboutStore/AboutStorePanel.tsx | |
| +++ b/src/pages/Settings/AboutStore/AboutStorePanel.tsx | |
| @@ -4,7 +4,6 @@ import { USStateSelect } from "components/common/USStateSelect/USStateSelect"; | |
| import { FormInput } from "components/CreateItem/common/FormInput"; | |
| import { FormLabel } from "components/CreateItem/common/FormLabel"; | |
| import { SettingsBlock } from "components/SettingsComponents/SettingsBlock"; | |
| -import { SubscriptionStatusBadge } from "components/SubscriptionStatusBadge"; | |
| import { Button } from "components/ui/button"; | |
| import { | |
| Form, | |
| @@ -13,7 +12,6 @@ import { | |
| FormItem, | |
| FormMessage, | |
| } from "components/ui/form"; | |
| -import { LoadingSpinner } from "components/ui/loading-spinner"; | |
| import { | |
| Select, | |
| SelectContent, | |
| @@ -23,16 +21,10 @@ import { | |
| } from "components/ui/select"; | |
| import { useToast } from "components/ui/use-toast"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useAppVersion } from "context/AppVersionContext"; | |
| import { useEntitySelected } from "context/EntityProvider"; | |
| -import { usePermissions } from "context/PermissionsContext"; | |
| import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| -import { CreditCard, Receipt } from "lucide-react"; | |
| -import { useMemo } from "react"; | |
| import { ControllerRenderProps, FieldPath, useForm } from "react-hook-form"; | |
| import { usePatchEntity } from "src/spring-generated"; | |
| -import { useGenerateEntitySubscriptionPaymentLink } from "src/spring-generated/hooks/useGenerateEntitySubscriptionPaymentLink"; | |
| -import { useGetEntitySubscriptionStatus } from "src/spring-generated/hooks/useGetEntitySubscriptionStatus"; | |
| import type { AddressRequest } from "src/spring-generated/types/AddressRequest"; | |
| import { extractAxios400ErrorMessage } from "utils/errors"; | |
| import * as z from "zod"; | |
| @@ -58,27 +50,8 @@ type AboutStoreFormValues = z.infer<typeof AboutStoreFormSchema>; | |
| export const AboutStorePanel = () => { | |
| useDocumentTitle("Settings - About Store"); | |
| - const { currentVersion, originDomain, stackName, servedFrom } = | |
| - useAppVersion(); | |
| const [entity, refreshEntity] = useEntitySelected(); | |
| const { toast } = useToast(); | |
| - const { hasPermission } = usePermissions(); | |
| - const hasSubscriptionReadStatusPermission = useMemo( | |
| - () => | |
| - hasPermission("esub/*:read_status") && | |
| - entity.subscriptionId !== undefined && | |
| - entity.subscriptionId !== null && | |
| - entity.subscriptionId !== "", | |
| - [hasPermission, entity?.subscriptionId], | |
| - ); | |
| - const hasSubscriptionReadPaymentLinkPermission = useMemo( | |
| - () => | |
| - hasPermission("esub/*:read_payment_link") && | |
| - entity.customerId !== undefined && | |
| - entity.customerId !== null && | |
| - entity.customerId !== "", | |
| - [hasPermission, entity?.customerId], | |
| - ); | |
| const { mutateAsync: patchEntity, isPending } = usePatchEntity({ | |
| mutation: { | |
| @@ -247,15 +220,6 @@ export const AboutStorePanel = () => { | |
| label="Merchant Processor Account ID" | |
| value={entity.creditCardMerchantId ?? "N/A"} | |
| /> | |
| - <ReadOnlyField label="Version" value={currentVersion} /> | |
| - <ReadOnlyField | |
| - label="Stack Name" | |
| - value={stackName ?? "Unknown"} | |
| - /> | |
| - <ReadOnlyField | |
| - label="Served From" | |
| - value={servedFrom ?? "Unknown"} | |
| - /> | |
| <ReadOnlyField | |
| label="Surcharge Fee" | |
| value={entity.surchargeFee ? "YES" : "NO"} | |
| @@ -376,17 +340,6 @@ export const AboutStorePanel = () => { | |
| </div> | |
| </form> | |
| </Form> | |
| - {(hasSubscriptionReadStatusPermission || | |
| - hasSubscriptionReadPaymentLinkPermission) && ( | |
| - <BillingSection | |
| - hasSubscriptionReadStatusPermission={ | |
| - hasSubscriptionReadStatusPermission | |
| - } | |
| - hasSubscriptionReadPaymentLinkPermission={ | |
| - hasSubscriptionReadPaymentLinkPermission | |
| - } | |
| - /> | |
| - )} | |
| </SettingsBlock> | |
| ); | |
| }; | |
| @@ -459,128 +412,3 @@ const EditableField = <T extends FieldPath<AboutStoreFormValues>>({ | |
| )} | |
| /> | |
| ); | |
| - | |
| -const BillingSection = ({ | |
| - hasSubscriptionReadStatusPermission, | |
| - hasSubscriptionReadPaymentLinkPermission, | |
| -}: { | |
| - hasSubscriptionReadStatusPermission: boolean; | |
| - hasSubscriptionReadPaymentLinkPermission: boolean; | |
| -}) => { | |
| - const [entity] = useEntitySelected(); | |
| - const { toast } = useToast(); | |
| - | |
| - // Get subscription status | |
| - const { data: subscriptionStatus } = useGetEntitySubscriptionStatus( | |
| - { | |
| - entityId: entity?.id ?? 0, | |
| - }, | |
| - { | |
| - query: { | |
| - enabled: !!entity?.id && hasSubscriptionReadStatusPermission, | |
| - queryKey: ["entitySubscriptionStatus", entity?.id], | |
| - throwOnError: false, | |
| - }, | |
| - }, | |
| - ); | |
| - | |
| - // Get payment link mutation | |
| - const { | |
| - mutateAsync: generatePaymentLink, | |
| - isPending: isGeneratingPaymentLink, | |
| - } = useGenerateEntitySubscriptionPaymentLink({ | |
| - mutation: { | |
| - onSuccess: (paymentUrl) => { | |
| - // Open payment link in new tab | |
| - if ( | |
| - paymentUrl === "" || | |
| - paymentUrl === null || | |
| - paymentUrl === undefined | |
| - ) { | |
| - toast({ | |
| - title: "Error generating payment link", | |
| - description: | |
| - "Please contact DrinksPOS Support. Your customer id may not be set in our system yet.", | |
| - variant: "destructive", | |
| - }); | |
| - return; | |
| - } | |
| - window.open(paymentUrl, "_blank"); | |
| - }, | |
| - }, | |
| - }); | |
| - | |
| - const handlePaymentClick = async () => { | |
| - if (!entity?.id) return; | |
| - | |
| - try { | |
| - await generatePaymentLink({ | |
| - params: { | |
| - entityId: entity.id, | |
| - }, | |
| - }); | |
| - } catch (error) { | |
| - console.error("Error generating payment link:", error); | |
| - captureException(error); | |
| - toast({ | |
| - title: "Error generating payment link", | |
| - description: "Failed to generate payment link. Please try again.", | |
| - variant: "destructive", | |
| - duration: 6000, | |
| - }); | |
| - } | |
| - }; | |
| - | |
| - if ( | |
| - !( | |
| - hasSubscriptionReadStatusPermission || | |
| - hasSubscriptionReadPaymentLinkPermission || | |
| - !subscriptionStatus | |
| - ) | |
| - ) { | |
| - return null; | |
| - } | |
| - | |
| - return ( | |
| - <div className="mt-8 w-full"> | |
| - <div className="flex items-center justify-between mb-4"> | |
| - <div> | |
| - <h2 className="text-xl font-semibold">Billing & Subscription</h2> | |
| - <p className="text-sm text-muted-foreground mt-1"> | |
| - Manage your subscription and billing information | |
| - </p> | |
| - </div> | |
| - <CreditCard className="h-6 w-6 text-muted-foreground" /> | |
| - </div> | |
| - | |
| - <div className="w-full flex flex-col justify-start gap-4"> | |
| - <div className="flex items-center justify-between"> | |
| - {hasSubscriptionReadStatusPermission && ( | |
| - <div className="flex items-center gap-3"> | |
| - <h3 className="font-medium">DrinksPOS Subscription</h3> | |
| - <SubscriptionStatusBadge | |
| - status={subscriptionStatus || "unknown"} | |
| - className="font-semibold text-xs px-3 py-1.5 rounded-full border-0 shadow-sm" | |
| - /> | |
| - </div> | |
| - )} | |
| - | |
| - {hasSubscriptionReadPaymentLinkPermission && ( | |
| - <Button | |
| - onClick={handlePaymentClick} | |
| - disabled={isGeneratingPaymentLink} | |
| - className="flex items-center gap-2" | |
| - > | |
| - {isGeneratingPaymentLink ? ( | |
| - <LoadingSpinner /> | |
| - ) : ( | |
| - <Receipt className="h-4 w-4" /> | |
| - )} | |
| - {isGeneratingPaymentLink ? "Processing..." : "Manage Billing"} | |
| - </Button> | |
| - )} | |
| - </div> | |
| - </div> | |
| - </div> | |
| - ); | |
| -}; | |
| diff --git a/src/pages/Settings/Devices/DeviceManagementPanel.tsx b/src/pages/Settings/Devices/DeviceManagementPanel.tsx | |
| index 09255b11..1d0ad901 100644 | |
| --- a/src/pages/Settings/Devices/DeviceManagementPanel.tsx | |
| +++ b/src/pages/Settings/Devices/DeviceManagementPanel.tsx | |
| @@ -1,22 +1,15 @@ | |
| -import { | |
| - Button, | |
| - Heading, | |
| - HStack, | |
| - Text, | |
| - useToast, | |
| - VStack, | |
| -} from "@chakra-ui/react"; | |
| +import { Button, HStack, Heading, VStack, useToast } from "@chakra-ui/react"; | |
| import { Card, List } from "@tremor/react"; | |
| import { BackToSettingsButton } from "components/SettingsComponents/BackToSettingsButton"; | |
| import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| import { useEffect } from "react"; | |
| -import { EraseDatabaseButton } from "src/components/common/EraseDatabaseButton"; | |
| import { StyledPaginationControls } from "src/components/common/StyledPaginationControls/StyledPaginationControls"; | |
| import * as Sentry from "src/config/sentry/TransformitySentry"; | |
| import { useEntity } from "src/context/EntityProvider"; | |
| import { useGetRegistersForEntity } from "src/generated"; | |
| import { NumberParam, useQueryParam, withDefault } from "use-query-params"; | |
| import { useRequestCashDrawer } from "../../../components/CashDrawer"; | |
| +import { useRequestPoleDisplay } from "../../../components/PoleDisplay"; | |
| import { RegisterListItem } from "./RegisterListItem"; | |
| export type DeviceManagementPanelProps = {}; | |
| @@ -28,6 +21,7 @@ const DeviceManagementPanelInner: React.FC<DeviceManagementPanelProps> = () => { | |
| const [entity] = useEntity(); | |
| const toast = useToast(); | |
| const requestCashDrawer = useRequestCashDrawer(); | |
| + const requestPoleDisplay = useRequestPoleDisplay(); | |
| const { data: registers, error: registersError } = useGetRegistersForEntity( | |
| entity?.id ?? 0, | |
| { | |
| @@ -75,6 +69,16 @@ const DeviceManagementPanelInner: React.FC<DeviceManagementPanelProps> = () => { | |
| </Card> | |
| <Card> | |
| <HStack w="100%" justifyContent="flex-start"> | |
| + <VStack | |
| + w="100%" | |
| + justifyContent="space-between" | |
| + alignItems="flex-start" | |
| + > | |
| + <Heading size="md">Pole Display</Heading> | |
| + <Button variant="outline" onClick={() => requestPoleDisplay()}> | |
| + Set up Pole Display | |
| + </Button> | |
| + </VStack> | |
| <VStack | |
| w="100%" | |
| justifyContent="space-between" | |
| @@ -87,24 +91,6 @@ const DeviceManagementPanelInner: React.FC<DeviceManagementPanelProps> = () => { | |
| </VStack> | |
| </HStack> | |
| </Card> | |
| - <Card> | |
| - <VStack w="100%" alignItems="flex-start"> | |
| - <Heading size="md">Local Database</Heading> | |
| - <Text fontSize="sm" color="gray.600" mb={4}> | |
| - Manage the local database used for offline functionality and | |
| - caching. | |
| - </Text> | |
| - <HStack w="100%" justifyContent="space-between" alignItems="center"> | |
| - <VStack alignItems="flex-start" spacing={1}> | |
| - <Text fontWeight="medium">Database Status</Text> | |
| - <Text fontSize="sm" color="gray.600"> | |
| - Active - storing transaction and product data | |
| - </Text> | |
| - </VStack> | |
| - <EraseDatabaseButton /> | |
| - </HStack> | |
| - </VStack> | |
| - </Card> | |
| </VStack> | |
| ); | |
| }; | |
| diff --git a/src/pages/Settings/EntityConfiguration/EntityConfiguationPanel.tsx b/src/pages/Settings/EntityConfiguration/EntityConfiguationPanel.tsx | |
| index 1d14d34b..234d2e06 100644 | |
| --- a/src/pages/Settings/EntityConfiguration/EntityConfiguationPanel.tsx | |
| +++ b/src/pages/Settings/EntityConfiguration/EntityConfiguationPanel.tsx | |
| @@ -53,6 +53,7 @@ type EntityConfigKeyWOFeeReport = Exclude< | |
| | EntityConfigKey.CUSTOMER_FACING_DISPLAY_LOGO | |
| | EntityConfigKey.TERMINAL_SCREEN_LOGO | |
| | EntityConfigKey.ENABLE_SALE_HOTKEYS | |
| + | EntityConfigKey.SHOW_CASHIER_ON_RECEIPT | |
| >; | |
| const entityConfigMap: Record< | |
| @@ -214,7 +215,7 @@ const entityConfigMap: Record< | |
| [EntityConfigKey.ORDER_MULTIPLE_ITEMS_POPUP]: { | |
| type: z.string().optional(), | |
| label: "Order Multiple Items Popup By:", | |
| - defaultValue: "ci_deposit_multiplier,asc", | |
| + defaultValue: "cohortItem.depositMultiplier,asc", | |
| component: ({ field, defaultValue }) => { | |
| const [selectedField, selectedDirection] = ( | |
| (field.value as string) || (defaultValue as string) | |
| @@ -223,7 +224,7 @@ const entityConfigMap: Record< | |
| const values = [ | |
| { | |
| label: "Deposit Multiplier", | |
| - value: "ci_deposit_multiplier", | |
| + value: "cohortItem.depositMultiplier", | |
| }, | |
| { | |
| label: "Price", | |
| @@ -231,7 +232,7 @@ const entityConfigMap: Record< | |
| }, | |
| { | |
| label: "Name", | |
| - value: "ci_name", | |
| + value: "cohortItem.name", | |
| }, | |
| ]; | |
| @@ -321,11 +322,6 @@ const entityConfigMap: Record< | |
| label: "Print Receipt on Refund", | |
| defaultValue: false, | |
| }, | |
| - [EntityConfigKey.SHOW_CASHIER_ON_RECEIPT]: { | |
| - type: z.boolean().optional(), | |
| - label: "Show Cashier on Receipt", | |
| - defaultValue: true, | |
| - }, | |
| }; | |
| const EntityConfigurationFormSchema = z.object( | |
| @@ -555,7 +551,6 @@ const Configuration = forwardRef<HTMLFormElement, ConfigurationProps>( | |
| return null; | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [configKey, defaultValue], | |
| ); | |
| diff --git a/src/pages/Settings/PriceLevels/PriceLevelsSettingsPanel.tsx b/src/pages/Settings/PriceLevels/PriceLevelsSettingsPanel.tsx | |
| index f93a1dd2..17d77814 100644 | |
| --- a/src/pages/Settings/PriceLevels/PriceLevelsSettingsPanel.tsx | |
| +++ b/src/pages/Settings/PriceLevels/PriceLevelsSettingsPanel.tsx | |
| @@ -44,7 +44,6 @@ export const PriceLevelsSettingsPanel: React.FC = () => { | |
| if (!isDialogOpen) { | |
| void refetch(); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [isDialogOpen]); | |
| const columns = [ | |
| diff --git a/src/pages/Settings/Roles/CreateUpdateRoleModal.tsx b/src/pages/Settings/Roles/CreateUpdateRoleModal.tsx | |
| index fa2578e0..d6bb00bc 100644 | |
| --- a/src/pages/Settings/Roles/CreateUpdateRoleModal.tsx | |
| +++ b/src/pages/Settings/Roles/CreateUpdateRoleModal.tsx | |
| @@ -23,7 +23,7 @@ import { RoleForm } from "./RoleForm"; | |
| import { RoleManagementCategory } from "./RoleManagementCategory"; | |
| export type PermissionDescription = { | |
| - permissionGroup: string[]; | |
| + permission: string; | |
| description: string; | |
| displayName: string; | |
| }; | |
| @@ -272,7 +272,6 @@ export const CreateUpdateRoleModal = ({ | |
| "shelftalker", | |
| "audit_log", | |
| "payment_option", | |
| - "esub", | |
| ], | |
| ) | |
| } | |
| @@ -309,18 +308,18 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "entity", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["entity/*:remote"], | |
| + permission: "entity/*:remote", | |
| description: | |
| "Ability to access the system remotely (on a personal device).", | |
| displayName: "Personal Access", | |
| }, | |
| { | |
| - permissionGroup: ["entity/*:manage", "entity/*:stream_health_check"], | |
| + permission: "entity/*:manage", | |
| description: "Ability to update settings and roles for this store.", | |
| displayName: "Manage Store", | |
| }, | |
| { | |
| - permissionGroup: ["entity/*:stats"], | |
| + permission: "entity/*:stats", | |
| description: "Ability to view business metrics (Margin, Profit, etc.).", | |
| displayName: "View Stats", | |
| }, | |
| @@ -331,27 +330,27 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "user", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["user/*:read"], | |
| + permission: "user/*:read", | |
| description: "Ability to read users.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["user/*:manage"], | |
| + permission: "user/*:manage", | |
| description: "Ability to manage users.", | |
| displayName: "Manage", | |
| }, | |
| { | |
| - permissionGroup: ["user/*:change-pin"], | |
| + permission: "user/*:change-pin", | |
| description: "Ability to change other users' pins.", | |
| displayName: "Change Pin", | |
| }, | |
| { | |
| - permissionGroup: ["user/*:delete"], | |
| + permission: "user/*:delete", | |
| description: "Ability to remove users.", | |
| displayName: "Delete", | |
| }, | |
| { | |
| - permissionGroup: ["user/*:invite"], | |
| + permission: "user/*:invite", | |
| description: "Ability to add new users.", | |
| displayName: "Add", | |
| }, | |
| @@ -362,49 +361,49 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "item", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["item/*:read"], | |
| + permission: "item/*:read", | |
| description: "Ability to read items.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:manage-prices"], | |
| + permission: "item/*:manage-prices", | |
| description: "Ability to manage item prices.", | |
| displayName: "Manage Prices", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:manage-inventory-pricing"], | |
| + permission: "item/*:manage-inventory-pricing", | |
| description: | |
| "Ability to manage store-specific item details (quantity, costs, etc.).", | |
| displayName: "Manage Store Fields", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:manage-vendors"], | |
| + permission: "item/*:manage-vendors", | |
| description: "Ability to manage item vendors", | |
| displayName: "Manage Item Vendors", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:manage-item-details"], | |
| + permission: "item/*:manage-item-details", | |
| description: | |
| "Ability to manage item details (name, department, case size, pack size, deposits, etc.).", | |
| displayName: "Manage Shared Fields", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:delete"], | |
| + permission: "item/*:delete", | |
| description: "Ability to delete items.", | |
| displayName: "Delete", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:exclusive"], | |
| + permission: "item/*:exclusive", | |
| description: "Ability to manage exclusive items.", | |
| displayName: "Exclusive", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:stats"], | |
| + permission: "item/*:stats", | |
| description: "Ability to see cost, profit stats per item.", | |
| displayName: "Statistics", | |
| }, | |
| { | |
| - permissionGroup: ["item/*:barcode"], | |
| + permission: "item/*:barcode", | |
| description: "Ability to manage item barcodes", | |
| displayName: "Barcode", | |
| }, | |
| @@ -415,17 +414,17 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "civin", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["civin/*:create"], | |
| + permission: "civin/*:create", | |
| description: "Ability to create item vintage", | |
| displayName: "Create Vintage", | |
| }, | |
| { | |
| - permissionGroup: ["civin/*:update"], | |
| + permission: "civin/*:update", | |
| description: "Ability to update item vintage", | |
| displayName: "Update Vintage", | |
| }, | |
| { | |
| - permissionGroup: ["civin/*:delete"], | |
| + permission: "civin/*:delete", | |
| description: "Ability to delete item vintage", | |
| displayName: "Delete Vintage", | |
| }, | |
| @@ -436,17 +435,17 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "item_list", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["item_list/*:read"], | |
| + permission: "item_list/*:read", | |
| description: "Ability to read item lists.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["item_list/*:manage"], | |
| + permission: "item_list/*:manage", | |
| description: "Ability to manage item lists.", | |
| displayName: "Manage", | |
| }, | |
| { | |
| - permissionGroup: ["item_list/*:delete"], | |
| + permission: "item_list/*:delete", | |
| description: "Ability to delete item lists.", | |
| displayName: "Delete", | |
| }, | |
| @@ -457,68 +456,68 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "pos", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["pos:discount-total"], | |
| + permission: "pos:discount-total", | |
| description: "Ability to apply discounts for the entire order.", | |
| displayName: "Discount Total", | |
| }, | |
| { | |
| - permissionGroup: ["pos:discount-line-item"], | |
| + permission: "pos:discount-line-item", | |
| description: "Ability to apply discounts for individual items.", | |
| displayName: "Discount Line Item", | |
| }, | |
| { | |
| - permissionGroup: ["pos:edit-price"], | |
| + permission: "pos:edit-price", | |
| description: "Ability to edit the price of an item on the sale screen.", | |
| displayName: "Edit Price", | |
| }, | |
| { | |
| - permissionGroup: ["pos:payout"], | |
| + permission: "pos:payout", | |
| description: "Ability to do a payout on the sales screen.", | |
| displayName: "Payout", | |
| }, | |
| { | |
| - permissionGroup: ["pos:sell-negative-quantity"], | |
| + permission: "pos:sell-negative-quantity", | |
| description: "Ability to sell negative quantity items.", | |
| displayName: "Sell Negative Quantity", | |
| }, | |
| { | |
| - permissionGroup: ["pos:change-sales-channel"], | |
| + permission: "pos:change-sales-channel", | |
| description: "Ability to change the sales channel of a sale.", | |
| displayName: "Change Sales Channel", | |
| }, | |
| { | |
| - permissionGroup: ["pos:remove-item"], | |
| + permission: "pos:remove-item", | |
| description: "Ability to remove items from cart.", | |
| displayName: "Remove Item", | |
| }, | |
| { | |
| - permissionGroup: ["pos:increase-quantity"], | |
| + permission: "pos:increase-quantity", | |
| description: "Ability to increase the quantity of an item in cart.", | |
| displayName: "Increase Quantity", | |
| }, | |
| { | |
| - permissionGroup: ["pos:decrease-quantity"], | |
| + permission: "pos:decrease-quantity", | |
| description: "Ability to decrease the quantity of an item in cart.", | |
| displayName: "Decrease Quantity", | |
| }, | |
| { | |
| - permissionGroup: ["pos:add-from-search"], | |
| + permission: "pos:add-from-search", | |
| description: | |
| "Ability to add items to a sale by text based search (i.e. without scanning a barcode).", | |
| displayName: "Add from Search", | |
| }, | |
| { | |
| - permissionGroup: ["pos:tax-exempt"], | |
| + permission: "pos:tax-exempt", | |
| description: "Ability to apply tax exemption on sales.", | |
| displayName: "Tax Exempt", | |
| }, | |
| { | |
| - permissionGroup: ["pos:reset-cart"], | |
| + permission: "pos:reset-cart", | |
| description: "Ability to reset cart on the sales screen", | |
| displayName: "Reset Cart", | |
| }, | |
| { | |
| - permissionGroup: ["pos:new-item"], | |
| + permission: "pos:new-item", | |
| description: "Ability to use the New Item button on the sales screen", | |
| displayName: "New Item", | |
| }, | |
| @@ -529,7 +528,7 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "price_level", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["price_level/*:manage"], | |
| + permission: "price_level/*:manage", | |
| description: "Ability to manage price levels.", | |
| displayName: "Manage", | |
| }, | |
| @@ -540,18 +539,13 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "saleschannel", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["saleschannel/*:read", "escpm/*:read"], | |
| - description: "Ability to read sales channels and ESCPM data.", | |
| + permission: "saleschannel/*:read", | |
| + description: "Ability to read sales channels.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: [ | |
| - "saleschannel/*:manage", | |
| - "escpm/*:create", | |
| - "escpm/*:update", | |
| - "escpm/*:delete", | |
| - ], | |
| - description: "Ability to manage sales channels and ESCPM data.", | |
| + permission: "saleschannel/*:manage", | |
| + description: "Ability to manage sales channels.", | |
| displayName: "Manage", | |
| }, | |
| ], | |
| @@ -561,12 +555,12 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "department", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["department/*:manage-group"], | |
| + permission: "department/*:manage-group", | |
| description: "Ability to manage department groups.", | |
| displayName: "Manage Group", | |
| }, | |
| { | |
| - permissionGroup: ["department/*:manage-department"], | |
| + permission: "department/*:manage-department", | |
| description: "Ability to manage departments.", | |
| displayName: "Manage Department", | |
| }, | |
| @@ -577,22 +571,22 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "transaction", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["transaction/*:read"], | |
| + permission: "transaction/*:read", | |
| description: "Ability to read transactions.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["transaction/*:search"], | |
| + permission: "transaction/*:search", | |
| description: "Ability to search transactions.", | |
| displayName: "Search", | |
| }, | |
| { | |
| - permissionGroup: ["transaction/*:void"], | |
| - description: "Ability to refund transactions.", | |
| - displayName: "Refund", | |
| + permission: "transaction/*:void", | |
| + description: "Ability to void transactions.", | |
| + displayName: "Void", | |
| }, | |
| { | |
| - permissionGroup: ["transaction/*:read-shift-totals"], | |
| + permission: "transaction/*:read-shift-totals", | |
| description: "Ability to read shift totals", | |
| displayName: "Read Shift Totals", | |
| }, | |
| @@ -603,17 +597,17 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "promotion", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["promotion/*:read"], | |
| + permission: "promotion/*:read", | |
| description: "Ability to read promotions.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["promotion/*:create"], | |
| + permission: "promotion/*:create", | |
| description: "Ability to create promotions.", | |
| displayName: "Create", | |
| }, | |
| { | |
| - permissionGroup: ["promotion/*:manage"], | |
| + permission: "promotion/*:manage", | |
| description: "Ability to manage promotions.", | |
| displayName: "Manage", | |
| }, | |
| @@ -624,17 +618,17 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "invoice", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["invoice/*:read"], | |
| + permission: "invoice/*:read", | |
| description: "Ability to read invoices.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["invoice/*:draft"], | |
| + permission: "invoice/*:draft", | |
| description: "Ability to draft invoices.", | |
| displayName: "Draft", | |
| }, | |
| { | |
| - permissionGroup: ["invoice/*:receive"], | |
| + permission: "invoice/*:receive", | |
| description: "Ability to set prices, receive invoices.", | |
| displayName: "Receive", | |
| }, | |
| @@ -645,17 +639,17 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "purchaseorder", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["purchaseorder/*:read"], | |
| + permission: "purchaseorder/*:read", | |
| description: "Open and view purchase orders.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["purchaseorder/*:draft"], | |
| + permission: "purchaseorder/*:draft", | |
| description: "Ability to draft purchase orders.", | |
| displayName: "Draft", | |
| }, | |
| { | |
| - permissionGroup: ["purchaseorder/*:receive"], | |
| + permission: "purchaseorder/*:receive", | |
| description: "Ability to receive purchase orders.", | |
| displayName: "Receive", | |
| }, | |
| @@ -666,32 +660,32 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "vendor", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["vendor/*:read"], | |
| + permission: "vendor/*:read", | |
| description: "Ability to see vendors.", | |
| displayName: "See Vendors", | |
| }, | |
| { | |
| - permissionGroup: ["vendor/*:exclusive"], | |
| + permission: "vendor/*:exclusive", | |
| description: "Ability to see exclusive vendors.", | |
| displayName: "See Exclusive Vendors", | |
| }, | |
| { | |
| - permissionGroup: ["vendor/*:manage-store-vendors"], | |
| + permission: "vendor/*:manage-store-vendors", | |
| description: "Ability to manage vendors at the store level.", | |
| displayName: "Manage Store Vendors", | |
| }, | |
| { | |
| - permissionGroup: ["vendor/*:manage-cohort-vendors"], | |
| + permission: "vendor/*:manage-cohort-vendors", | |
| description: "Ability to manage vendors across the group of stores.", | |
| displayName: "Manage Vendors", | |
| }, | |
| { | |
| - permissionGroup: ["vendor/*:read-vendor-groups"], | |
| + permission: "vendor/*:read-vendor-groups", | |
| description: "Ability to read vendor groups.", | |
| displayName: "Read Vendor Groups", | |
| }, | |
| { | |
| - permissionGroup: ["vendor/*:manage-vendor-groups"], | |
| + permission: "vendor/*:manage-vendor-groups", | |
| description: "Ability to manage vendor groups.", | |
| displayName: "Manage Vendor Groups", | |
| }, | |
| @@ -702,27 +696,27 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "loyalty", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["loyalty/*:read"], | |
| + permission: "loyalty/*:read", | |
| description: "Ability to read loyalty program settings.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["loyalty/*:manage"], | |
| + permission: "loyalty/*:manage", | |
| description: "Ability to manage loyalty program settings.", | |
| displayName: "Manage", | |
| }, | |
| { | |
| - permissionGroup: ["loyalty/*:entity-stats"], | |
| + permission: "loyalty/*:entity-stats", | |
| description: "Ability to view entity statistics.", | |
| displayName: "View Entity Stats", | |
| }, | |
| { | |
| - permissionGroup: ["loyalty/*:manageCustomerInformation"], | |
| + permission: "loyalty/*:manageCustomerInformation", | |
| description: "Ability to manage customer basic info", | |
| displayName: "Manage Basic Info", | |
| }, | |
| { | |
| - permissionGroup: ["loyalty/*:manageCustomerPricingInfo"], | |
| + permission: "loyalty/*:manageCustomerPricingInfo", | |
| description: "Ability to manage customer advanced info", | |
| displayName: "Manage Advanced Info", | |
| }, | |
| @@ -733,27 +727,27 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "campaign", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["campaign/*:read"], | |
| + permission: "campaign/*:read", | |
| description: "Ability to read campaigns.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["campaign/*:update"], | |
| + permission: "campaign/*:update", | |
| description: "Ability to update campaigns.", | |
| displayName: "Update", | |
| }, | |
| { | |
| - permissionGroup: ["campaign/*:create"], | |
| + permission: "campaign/*:create", | |
| description: "Ability to create campaigns.", | |
| displayName: "Create", | |
| }, | |
| { | |
| - permissionGroup: ["campaign/*:trigger"], | |
| + permission: "campaign/*:trigger", | |
| description: "Ability to trigger campaigns.", | |
| displayName: "Trigger", | |
| }, | |
| { | |
| - permissionGroup: ["campaign/*:delete"], | |
| + permission: "campaign/*:delete", | |
| description: "Ability to delete campaigns.", | |
| displayName: "Delete", | |
| }, | |
| @@ -764,22 +758,22 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "customerhouseaccount", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["customerhouseaccount/*:read"], | |
| + permission: "customerhouseaccount/*:read", | |
| description: "Ability to read customer house accounts.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["customerhouseaccount/*:create"], | |
| + permission: "customerhouseaccount/*:create", | |
| description: "Ability to create customer house accounts.", | |
| displayName: "Create", | |
| }, | |
| { | |
| - permissionGroup: ["customerhouseaccount/*:update"], | |
| + permission: "customerhouseaccount/*:update", | |
| description: "Ability to update customer house accounts once created.", | |
| displayName: "Update", | |
| }, | |
| { | |
| - permissionGroup: ["customerhouseaccount/*:update-credit-limit"], | |
| + permission: "customerhouseaccount/*:update-credit-limit", | |
| description: "Ability to update credit limits on a house account.", | |
| displayName: "Update Credit Limit", | |
| }, | |
| @@ -790,17 +784,17 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "inventory_transfers", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["inventory_transfers/*:read"], | |
| + permission: "inventory_transfers/*:read", | |
| description: "Open and view inventory transfers.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["inventory_transfers/*:manage"], | |
| + permission: "inventory_transfers/*:manage", | |
| description: "Ability to manage inventory transfers.", | |
| displayName: "Manage", | |
| }, | |
| { | |
| - permissionGroup: ["inventory_transfers/*:merge"], | |
| + permission: "inventory_transfers/*:merge", | |
| description: "Ability to merge inventory transfers.", | |
| displayName: "Merge", | |
| }, | |
| @@ -811,22 +805,22 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "inventory_count", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["inventory_count/*:read"], | |
| + permission: "inventory_count/*:read", | |
| description: "Open and view inventory counts.", | |
| displayName: "Read", | |
| }, | |
| { | |
| - permissionGroup: ["inventory_count/*:count"], | |
| + permission: "inventory_count/*:count", | |
| description: "Ability to count items in an inventory count.", | |
| displayName: "Count", | |
| }, | |
| { | |
| - permissionGroup: ["inventory_count/*:complete-rotate"], | |
| + permission: "inventory_count/*:complete-rotate", | |
| description: "Ability to complete inventory rotational counts", | |
| displayName: "Complete rotational count", | |
| }, | |
| { | |
| - permissionGroup: ["inventory_count/*:complete-full"], | |
| + permission: "inventory_count/*:complete-full", | |
| description: "Ability to complete inventory full store count", | |
| displayName: "Complete full store count", | |
| }, | |
| @@ -837,12 +831,12 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "shelftalker", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["shelftalker/*:manage-task"], | |
| + permission: "shelftalker/*:manage-task", | |
| description: "Ability to create and manage shelf talker tasks.", | |
| displayName: "Manage Tasks", | |
| }, | |
| { | |
| - permissionGroup: ["shelftalker/*:manage-preset"], | |
| + permission: "shelftalker/*:manage-preset", | |
| description: "Ability to manage shelf talker presets (templates).", | |
| displayName: "Manage Presets", | |
| }, | |
| @@ -853,38 +847,38 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "report", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["report/transactionReports:read"], | |
| + permission: "report/transactionReports:read", | |
| description: "Ability to read transaction reports.", | |
| displayName: "Transaction Reports", | |
| }, | |
| { | |
| - permissionGroup: ["report/paymentsProcessor:read"], | |
| + permission: "report/paymentsProcessor:read", | |
| description: | |
| "Ability to read payment processor reports, including ACH payouts.", | |
| displayName: "Payment Processor Reports", | |
| }, | |
| { | |
| - permissionGroup: ["report/itemReports:read"], | |
| + permission: "report/itemReports:read", | |
| description: "Ability to read item reports.", | |
| displayName: "Item Reports", | |
| }, | |
| { | |
| - permissionGroup: ["report/invoiceReports:read"], | |
| + permission: "report/invoiceReports:read", | |
| description: "Ability to read invoice reports.", | |
| displayName: "Invoice Reports", | |
| }, | |
| { | |
| - permissionGroup: ["report/inventoryReport:read"], | |
| + permission: "report/inventoryReport:read", | |
| description: "Ability to read inventory reports.", | |
| displayName: "Inventory Report", | |
| }, | |
| { | |
| - permissionGroup: ["report/totalsReport:read"], | |
| + permission: "report/totalsReport:read", | |
| description: "Ability to read totals reports.", | |
| displayName: "Totals Report", | |
| }, | |
| { | |
| - permissionGroup: ["report/todaysTotals:read"], | |
| + permission: "report/todaysTotals:read", | |
| description: "Ability to read todays total report.", | |
| displayName: "Today's Totals", | |
| }, | |
| @@ -895,22 +889,22 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "register", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["register/*:open"], | |
| + permission: "register/*:open", | |
| description: "Ability to open a register.", | |
| displayName: "Open", | |
| }, | |
| { | |
| - permissionGroup: ["register/*:change"], | |
| + permission: "register/*:change", | |
| description: "Ability to change a register.", | |
| displayName: "Change", | |
| }, | |
| { | |
| - permissionGroup: ["register/*:close"], | |
| + permission: "register/*:close", | |
| description: "Ability to close a register.", | |
| displayName: "Close", | |
| }, | |
| { | |
| - permissionGroup: ["register/*:pop"], | |
| + permission: "register/*:pop", | |
| description: "Ability to pop the cash drawer.", | |
| displayName: "Pop", | |
| }, | |
| @@ -921,90 +915,68 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "payment_option", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["payment_option/credit_card:use"], | |
| + permission: "payment_option/credit_card:use", | |
| description: "Ability to take credit card payments.", | |
| displayName: "Credit Card", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/cash:use"], | |
| + permission: "payment_option/cash:use", | |
| description: "Ability to take cash payments.", | |
| displayName: "Cash", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/manual_credit_card:use"], | |
| + permission: "payment_option/manual_credit_card:use", | |
| description: "Ability to take manual credit card payments.", | |
| displayName: "Manual Credit Card", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/check:use"], | |
| + permission: "payment_option/check:use", | |
| description: "Ability to take check payments.", | |
| displayName: "Check", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/gift_card:use"], | |
| + permission: "payment_option/gift_card:use", | |
| description: "Ability to take gift card payments.", | |
| displayName: "Gift Card", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/points:use"], | |
| + permission: "payment_option/points:use", | |
| description: "Ability to take loyalty points as payments.", | |
| displayName: "Loyalty Points", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/pay_later:use"], | |
| + permission: "payment_option/pay_later:use", | |
| description: "Ability to take pay later payments.", | |
| displayName: "Pay Later", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/multiple:use"], | |
| + permission: "payment_option/multiple:use", | |
| description: "Ability to take multiple payments.", | |
| displayName: "Multiple", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/other:use"], | |
| + permission: "payment_option/other:use", | |
| description: "Ability to take other payment methods.", | |
| displayName: "Other", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/house_account:use"], | |
| + permission: "payment_option/house_account:use", | |
| description: "Ability to take house account payments.", | |
| displayName: "House Account", | |
| }, | |
| { | |
| - permissionGroup: ["payment_option/payment_link:use"], | |
| + permission: "payment_option/payment_link:use", | |
| description: "Ability to create and take payment links as payments.", | |
| displayName: "Payment Link", | |
| }, | |
| ], | |
| }, | |
| - { | |
| - title: "Fulfillment", | |
| - resourceType: "fulfillment", | |
| - permissionDescriptions: [ | |
| - { | |
| - permissionGroup: ["fulfillment/*:update"], | |
| - description: "Ability to update fulfillment.", | |
| - displayName: "Update", | |
| - }, | |
| - ], | |
| - }, | |
| - { | |
| - title: "Order Item Decisions", | |
| - resourceType: "orderitemdecision", | |
| - permissionDescriptions: [ | |
| - { | |
| - permissionGroup: ["orderitemdecision/*:update-status"], | |
| - description: "Ability to accept or reject order item decisions.", | |
| - displayName: "Update Status", | |
| - }, | |
| - ], | |
| - }, | |
| { | |
| title: "Audit Log", | |
| resourceType: "audit_log", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["audit_log/*:read"], | |
| + permission: "audit_log/*:read", | |
| description: "Ability to see audit log.", | |
| displayName: "See Audit Log", | |
| }, | |
| @@ -1015,28 +987,11 @@ const permissionSettingsDescriptions: PermissionCategory[] = [ | |
| resourceType: "label", | |
| permissionDescriptions: [ | |
| { | |
| - permissionGroup: ["label/*:manage"], | |
| + permission: "label/*:manage", | |
| description: | |
| "Ability to create, import, and delete label printer templates.", | |
| displayName: "Manage", | |
| }, | |
| ], | |
| }, | |
| - { | |
| - title: "Billing", | |
| - resourceType: "esub", | |
| - permissionDescriptions: [ | |
| - { | |
| - permissionGroup: ["esub/*:read_subscription_status"], | |
| - description: "Ability to view subscription status.", | |
| - displayName: "Read Subscription Status", | |
| - }, | |
| - { | |
| - permissionGroup: ["esub/*:generate_subscription_link"], | |
| - description: | |
| - "Ability to access payment links for subscription billing.", | |
| - displayName: "Generate Subscription Payment Link", | |
| - }, | |
| - ], | |
| - }, | |
| ]; | |
| diff --git a/src/pages/Settings/Roles/RoleManagementCategory.tsx b/src/pages/Settings/Roles/RoleManagementCategory.tsx | |
| index 36b35bb6..54a22559 100644 | |
| --- a/src/pages/Settings/Roles/RoleManagementCategory.tsx | |
| +++ b/src/pages/Settings/Roles/RoleManagementCategory.tsx | |
| @@ -7,7 +7,12 @@ import { | |
| import { ChevronDownIcon } from "@radix-ui/react-icons"; | |
| import { useEffect } from "react"; | |
| import { useFormContext, useWatch } from "react-hook-form"; | |
| -import { PermissionDescription } from "./CreateUpdateRoleModal"; | |
| + | |
| +type PermissionDescription = { | |
| + permission: string; | |
| + description: string; | |
| + displayName: string; | |
| +}; | |
| export type RoleManagementCategoryProps = { | |
| title: string; | |
| @@ -30,41 +35,20 @@ export const RoleManagementCategory: React.FC<RoleManagementCategoryProps> = ({ | |
| const { register, setValue, watch, getValues, trigger } = useFormContext(); | |
| const value = useWatch({ name: "value" }); | |
| - // Helper function to get all permissions from a permission description | |
| - const getPermissionGroup = ( | |
| - permissionDesc: PermissionDescription, | |
| - ): string[] => { | |
| - return permissionDesc.permissionGroup; | |
| - }; | |
| - | |
| - // Helper function to check if all permissions from a description are selected | |
| - const arePermissionsSelected = ( | |
| - permissionDesc: PermissionDescription, | |
| - ): boolean => { | |
| - const permissions = getPermissionGroup(permissionDesc); | |
| - return permissions.every((perm) => value?.includes(perm)); | |
| - }; | |
| - | |
| - // Helper function to get all permissions from all descriptions | |
| - const getAllPermissions = (): string[] => { | |
| - return permissionDescriptions.flatMap(getPermissionGroup); | |
| - }; | |
| - | |
| useEffect(() => { | |
| - const allPermissions = getAllPermissions(); | |
| + const permissionList = permissionDescriptions.map((row) => row.permission); | |
| // If "All" checkbox is checked, remove all other checkboxes | |
| if ( | |
| value?.includes(`${resourceType}/*:*`) && | |
| - allPermissions.some((permission) => value.includes(permission)) | |
| + permissionList.some((permission) => value.includes(permission)) | |
| ) { | |
| setValue("value", [ | |
| ...value?.filter( | |
| - (permission: string) => !allPermissions.includes(permission), | |
| + (permission: string) => !permissionList.includes(permission), | |
| ), | |
| ]); | |
| void trigger("value"); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [permissionDescriptions, resourceType, setValue, trigger, value]); | |
| return ( | |
| @@ -90,7 +74,7 @@ export const RoleManagementCategory: React.FC<RoleManagementCategoryProps> = ({ | |
| value?.includes(`${resourceType}/*:*`) | |
| ? true | |
| : permissionDescriptions.some((row) => | |
| - arePermissionsSelected(row), | |
| + value?.includes(row.permission), | |
| ) | |
| ? "indeterminate" | |
| : false | |
| @@ -121,39 +105,26 @@ export const RoleManagementCategory: React.FC<RoleManagementCategoryProps> = ({ | |
| <CollapsibleContent className="p-4"> | |
| <div className="grid grid-cols-2 gap-4"> | |
| {permissionDescriptions.map((entry) => { | |
| - const { | |
| - permissionGroup: permissionGroup, | |
| - description, | |
| - displayName, | |
| - } = entry; | |
| - const permissions = getPermissionGroup(entry); | |
| - const key = Array.isArray(permissionGroup) | |
| - ? permissionGroup.join(",") | |
| - : permissionGroup; | |
| - | |
| + const { permission, description, displayName } = entry; | |
| return ( | |
| - <div key={key} className="flex items-start gap-2 flex-1"> | |
| + <div key={permission} className="flex items-start gap-2 flex-1"> | |
| <Checkbox | |
| checked={ | |
| value?.includes(`${resourceType}/*:*`) || | |
| - arePermissionsSelected(entry) | |
| + value?.includes(permission) | |
| } | |
| disabled={value?.includes(`${resourceType}/*:*`)} | |
| - value={permissions[0]} // Use first permission as the value for the checkbox | |
| + value={permission} | |
| {...register("value")} | |
| className="mt-1" | |
| onCheckedChange={(checked) => { | |
| const currentValue = getValues("value"); | |
| if (checked) { | |
| - // Add all permissions in the bundle | |
| - setValue("value", [...currentValue, ...permissions]); | |
| + setValue("value", [...currentValue, permission]); | |
| } else { | |
| - // Remove all permissions in the bundle | |
| setValue( | |
| "value", | |
| - currentValue.filter( | |
| - (v: string) => !permissions.includes(v), | |
| - ), | |
| + currentValue.filter((v: string) => v !== permission), | |
| ); | |
| } | |
| void trigger("value"); | |
| diff --git a/src/pages/Settings/SalesChannels/EditSalesChannelPage.tsx b/src/pages/Settings/SalesChannels/EditSalesChannelPage.tsx | |
| deleted file mode 100644 | |
| index 03c26b86..00000000 | |
| --- a/src/pages/Settings/SalesChannels/EditSalesChannelPage.tsx | |
| +++ /dev/null | |
| @@ -1,273 +0,0 @@ | |
| -import { Heading, Text } from "@chakra-ui/react"; | |
| -import { DefaultLayoutWithNavbar } from "components/layouts/DefaultLayoutWithNavbar"; | |
| -import { PageWithSidebar } from "components/layouts/PageWithSidebar"; | |
| -import { PaymentMethodManager } from "components/SalesChannels/PaymentMethodManager"; | |
| -import { SalesChannelBasicInfoStep } from "components/SalesChannels/SalesChannelBasicInfoStep"; | |
| -import { Button } from "components/ui/button"; | |
| -import { Card, CardContent, CardHeader, CardTitle } from "components/ui/card"; | |
| -import { LoadingSpinner } from "components/ui/loading-spinner"; | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| -import { SalesChannelFormData } from "hooks/useSalesChannelWizard"; | |
| -import { ChevronLeft } from "lucide-react"; | |
| -import React, { useCallback, useEffect, useMemo, useState } from "react"; | |
| -import { useForm } from "react-hook-form"; | |
| -import { useNavigate, useParams } from "react-router-dom"; | |
| -import { toast } from "sonner"; | |
| -import { | |
| - useGetEntitySalesChannelById, | |
| - useListSalesChannelDepartments, | |
| - useUpsertEntitySalesChannel, | |
| -} from "src/spring-generated"; | |
| -import { extractAxios400ErrorMessage } from "utils/errors"; | |
| - | |
| -export const EditSalesChannelPage: React.FC = () => { | |
| - const { id } = useParams<{ id: string }>(); | |
| - const navigate = useNavigate(); | |
| - const [entity] = useEntitySelected(); | |
| - const [selectedDepartments, setSelectedDepartments] = useState<number[]>([]); | |
| - | |
| - const salesChannelId = parseInt(id || "0"); | |
| - | |
| - useDocumentTitle(`Edit Sales Channel`); | |
| - | |
| - // Fetch sales channel data | |
| - const { | |
| - data: salesChannel, | |
| - isLoading: isLoadingSalesChannel, | |
| - error: salesChannelError, | |
| - } = useGetEntitySalesChannelById(salesChannelId, { | |
| - query: { | |
| - enabled: !!salesChannelId && salesChannelId > 0, | |
| - }, | |
| - }); | |
| - | |
| - // Fetch sales channel departments | |
| - const { | |
| - data: entitySalesChannelDepartments, | |
| - isFetching: isLoadingSalesChannelDepartments, | |
| - } = useListSalesChannelDepartments(salesChannelId, { | |
| - query: { | |
| - enabled: !!salesChannelId && salesChannelId > 0, | |
| - }, | |
| - }); | |
| - | |
| - const defaultValues = useMemo(() => { | |
| - if (!salesChannel) { | |
| - return { | |
| - entityId: entity?.id, | |
| - name: "", | |
| - salesChannelTypeId: 1, | |
| - active: false, | |
| - taxable: false, | |
| - autoAddNewDepartments: false, | |
| - allowNegativeInventory: false, | |
| - departmentIds: [], | |
| - paymentMethods: [], | |
| - }; | |
| - } | |
| - | |
| - return { | |
| - ...salesChannel, | |
| - departmentIds: [], | |
| - paymentMethods: [], | |
| - }; | |
| - }, [salesChannel, entity?.id]); | |
| - | |
| - const form = useForm<SalesChannelFormData>({ | |
| - defaultValues, | |
| - }); | |
| - | |
| - const { mutateAsync: upsertSalesChannel, isPending: isSaving } = | |
| - useUpsertEntitySalesChannel({ | |
| - mutation: { | |
| - onSuccess: () => { | |
| - toast.success("Sales channel updated successfully"); | |
| - }, | |
| - onError: (error) => { | |
| - console.log("Error updating sales channel:", error); | |
| - toast.error( | |
| - "Failed to update sales channel: " + | |
| - extractAxios400ErrorMessage(error), | |
| - ); | |
| - console.error("Error updating sales channel:", error); | |
| - captureException(error); | |
| - }, | |
| - }, | |
| - }); | |
| - | |
| - // Populate form when data loads | |
| - useEffect(() => { | |
| - if (salesChannel) { | |
| - if (entitySalesChannelDepartments) { | |
| - const departmentIds = entitySalesChannelDepartments.map( | |
| - (department) => department.id.departmentId, | |
| - ); | |
| - form.reset({ | |
| - ...defaultValues, | |
| - departmentIds, | |
| - }); | |
| - setSelectedDepartments(departmentIds); | |
| - } else { | |
| - form.reset(defaultValues); | |
| - setSelectedDepartments(defaultValues.departmentIds); | |
| - } | |
| - } | |
| - }, [salesChannel, entitySalesChannelDepartments, defaultValues, form]); | |
| - | |
| - // Update selectedDepartments when entitySalesChannelDepartments changes | |
| - useEffect(() => { | |
| - if (entitySalesChannelDepartments) { | |
| - const departmentIds = entitySalesChannelDepartments.map( | |
| - (department) => department.id.departmentId, | |
| - ); | |
| - console.log("Setting departments:", departmentIds); | |
| - setSelectedDepartments(departmentIds); | |
| - form.setValue("departmentIds", departmentIds); | |
| - } | |
| - }, [entitySalesChannelDepartments, form]); | |
| - | |
| - const handleBasicInfoSave = useCallback(async () => { | |
| - const values = form.getValues(); | |
| - | |
| - try { | |
| - await upsertSalesChannel({ | |
| - data: { | |
| - ...values, | |
| - id: salesChannelId, | |
| - }, | |
| - }); | |
| - } catch (error) { | |
| - // Error handling is done in the mutation | |
| - } | |
| - }, [form, upsertSalesChannel, salesChannelId]); | |
| - | |
| - // Define sidebar items for the sales channel settings | |
| - const sidebarItems = useMemo( | |
| - () => [ | |
| - { | |
| - id: "basic-info", | |
| - header: "Basic Information", | |
| - content: ( | |
| - <Card> | |
| - <CardHeader> | |
| - <CardTitle>Basic Information</CardTitle> | |
| - </CardHeader> | |
| - <CardContent className="space-y-6"> | |
| - <SalesChannelBasicInfoStep | |
| - form={form} | |
| - selectedDepartments={selectedDepartments} | |
| - setSelectedDepartments={setSelectedDepartments} | |
| - /> | |
| - | |
| - <div className="flex justify-end pt-4 border-t"> | |
| - <Button | |
| - onClick={handleBasicInfoSave} | |
| - disabled={isSaving} | |
| - className="min-w-[120px]" | |
| - > | |
| - {isSaving ? "Saving..." : "Save Changes"} | |
| - </Button> | |
| - </div> | |
| - </CardContent> | |
| - </Card> | |
| - ), | |
| - }, | |
| - { | |
| - id: "payment-methods", | |
| - header: "Payment Methods", | |
| - content: ( | |
| - <Card> | |
| - <CardHeader> | |
| - <CardTitle>Payment Methods</CardTitle> | |
| - </CardHeader> | |
| - <CardContent> | |
| - <PaymentMethodManager | |
| - form={form} | |
| - salesChannelId={salesChannelId} | |
| - /> | |
| - </CardContent> | |
| - </Card> | |
| - ), | |
| - }, | |
| - ], | |
| - [ | |
| - form, | |
| - selectedDepartments, | |
| - setSelectedDepartments, | |
| - isSaving, | |
| - salesChannelId, | |
| - handleBasicInfoSave, | |
| - ], | |
| - ); | |
| - | |
| - if (isLoadingSalesChannel || isLoadingSalesChannelDepartments) { | |
| - return ( | |
| - <DefaultLayoutWithNavbar pageTitle="Edit Sales Channel"> | |
| - <div className="flex items-center justify-center min-h-[400px]"> | |
| - <LoadingSpinner /> | |
| - </div> | |
| - </DefaultLayoutWithNavbar> | |
| - ); | |
| - } | |
| - | |
| - if (salesChannelError || !salesChannel) { | |
| - return ( | |
| - <DefaultLayoutWithNavbar pageTitle="Edit Sales Channel"> | |
| - <div className="max-w-4xl mx-auto p-6"> | |
| - <div className="text-center py-8"> | |
| - <h2 className="text-xl font-semibold text-gray-900 mb-2"> | |
| - Sales Channel Not Found | |
| - </h2> | |
| - <p className="text-gray-600 mb-4"> | |
| - The sales channel you're looking for doesn't exist or you don't | |
| - have permission to view it. | |
| - </p> | |
| - <Button | |
| - onClick={() => | |
| - navigate("/settings/sales-channels?tab=saleschannels") | |
| - } | |
| - > | |
| - Back to Sales Channels | |
| - </Button> | |
| - </div> | |
| - </div> | |
| - </DefaultLayoutWithNavbar> | |
| - ); | |
| - } | |
| - | |
| - return ( | |
| - <DefaultLayoutWithNavbar pageTitle="Edit Sales Channel"> | |
| - <div className="w-5/6 p-6"> | |
| - {/* Header */} | |
| - <div className="mb-6"> | |
| - <div className="flex items-center gap-4 mb-4"> | |
| - <Button | |
| - variant="ghost" | |
| - size="sm" | |
| - onClick={() => | |
| - navigate("/settings/sales-channels?tab=saleschannels") | |
| - } | |
| - className="flex items-center gap-2" | |
| - > | |
| - <ChevronLeft className="h-4 w-4" /> | |
| - Back to Sales Channels | |
| - </Button> | |
| - <div> | |
| - <Heading fontSize="2xl">{salesChannel.name}</Heading> | |
| - <Text fontSize="sm" fontWeight="normal"> | |
| - Sales Channel Settings | |
| - </Text> | |
| - </div> | |
| - </div> | |
| - </div> | |
| - | |
| - {/* Tabs */} | |
| - <PageWithSidebar orientation="horizontal" sidebarItems={sidebarItems} /> | |
| - </div> | |
| - </DefaultLayoutWithNavbar> | |
| - ); | |
| -}; | |
| - | |
| -export default EditSalesChannelPage; | |
| diff --git a/src/pages/Settings/SalesChannels/SalesChannelSettingsPanel.tsx b/src/pages/Settings/SalesChannels/SalesChannelSettingsPanel.tsx | |
| deleted file mode 100644 | |
| index 2837c2dd..00000000 | |
| --- a/src/pages/Settings/SalesChannels/SalesChannelSettingsPanel.tsx | |
| +++ /dev/null | |
| @@ -1,227 +0,0 @@ | |
| -import { useDisclosure, useToast } from "@chakra-ui/react"; | |
| -import { captureException } from "@sentry/react"; | |
| -import { useQueryClient } from "@tanstack/react-query"; | |
| -import { StyledPaginationControls } from "components/common/StyledPaginationControls/StyledPaginationControls"; | |
| -import { DeleteButtonWithWarning } from "components/DeleteButtonWithWarning"; | |
| -import { CreateSalesChannelWizardV2 } from "components/SalesChannels/CreateSalesChannelWizardV2"; | |
| -import { SalesChannelBadge } from "components/SalesChannels/SalesChannelBadge"; | |
| -import { SettingsBlock } from "components/SettingsComponents/SettingsBlock"; | |
| -import { Badge } from "components/ui/badge"; | |
| -import { Button } from "components/ui/button"; | |
| -import { | |
| - Tooltip, | |
| - TooltipContent, | |
| - TooltipProvider, | |
| - TooltipTrigger, | |
| -} from "components/ui/tooltip"; | |
| -import { useEntitySelected } from "context/EntityProvider"; | |
| -import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| -import { AlertCircle, PlusIcon } from "lucide-react"; | |
| -import { useNavigate } from "react-router-dom"; | |
| -import { | |
| - ApiPageEntitySalesChannel, | |
| - useDeleteSalesChannel, | |
| - useListSalesChannels, | |
| -} from "src/spring-generated"; | |
| -import { NumberParam, useQueryParams, withDefault } from "use-query-params"; | |
| -import { isAxios400 } from "utils/errors"; | |
| - | |
| -type SalesChannelSettingsPanelProps = {}; | |
| - | |
| -export const SalesChannelSettingsPanel: React.FC< | |
| - SalesChannelSettingsPanelProps | |
| -> = () => { | |
| - useDocumentTitle("Settings - Sales Channel"); | |
| - const [entity] = useEntitySelected(); | |
| - const queryClient = useQueryClient(); | |
| - const navigate = useNavigate(); | |
| - const [{ page }] = useQueryParams({ | |
| - page: withDefault(NumberParam, 1), | |
| - }); | |
| - const { data: salesChannels, queryKey } = useListSalesChannels({ | |
| - entityIds: [entity.id], | |
| - page: page - 1, | |
| - size: 30, | |
| - }); | |
| - | |
| - // Create disclosure | |
| - const createDisclosure = useDisclosure(); | |
| - | |
| - // Check for sales channels without default payment methods | |
| - const channelsWithoutDefaultPaymentMethod = | |
| - salesChannels?.content?.filter( | |
| - (channel) => !channel.defaultPaymentMethodId, | |
| - ) || []; | |
| - | |
| - return ( | |
| - <SettingsBlock | |
| - flexGrow={1} | |
| - header={ | |
| - <div className="w-full flex flex-row justify-between"> | |
| - <h1 className="text-2xl font-bold">Sales Channels</h1> | |
| - <Button onClick={createDisclosure.onOpen}> | |
| - <PlusIcon className="w-4 h-4 mr-2" /> | |
| - New Sales Channel | |
| - </Button> | |
| - </div> | |
| - } | |
| - > | |
| - <ul className="space-y-4 w-full flex-grow flex flex-col"> | |
| - {salesChannels?.content?.map((channel) => { | |
| - const hasNoDefaultPaymentMethod = !channel.defaultPaymentMethodId; | |
| - | |
| - return ( | |
| - <li | |
| - key={channel.id} | |
| - className={`flex items-center border-b justify-between p-2 rounded-md ${ | |
| - hasNoDefaultPaymentMethod | |
| - ? "border-orange-200 bg-orange-50" | |
| - : "" | |
| - }`} | |
| - > | |
| - <div> | |
| - <div className="flex flex-row items-center gap-2"> | |
| - <h3 className="font-semibold">{channel.name}</h3> | |
| - <SalesChannelBadge salesChannel={channel} /> | |
| - {hasNoDefaultPaymentMethod && ( | |
| - <Badge | |
| - variant="secondary" | |
| - className="text-xs text-orange-700 bg-orange-100 border-orange-200" | |
| - > | |
| - <AlertCircle className="w-3 h-3 mr-1" /> | |
| - No Default Payment Method | |
| - </Badge> | |
| - )} | |
| - </div> | |
| - {channel.accountId && ( | |
| - <p className="text-sm text-gray-600"> | |
| - Account ID: {channel.accountId} | |
| - </p> | |
| - )} | |
| - {hasNoDefaultPaymentMethod && ( | |
| - <p className="text-sm text-orange-600 mt-1"> | |
| - This sales channel needs a default payment method to work | |
| - properly. Please edit the sales channel. | |
| - </p> | |
| - )} | |
| - </div> | |
| - <div className="flex gap-2 items-center"> | |
| - <Badge>ID: {channel.id}</Badge> | |
| - <Badge variant={channel.active ? "successful" : "destructive"}> | |
| - {channel.active ? "Active" : "Inactive"} | |
| - </Badge> | |
| - <div className="flex flex-row gap-2"> | |
| - <Button | |
| - variant="outline" | |
| - disabled={false} | |
| - className="ml-4" | |
| - onClick={() => | |
| - navigate(`/settings/sales-channels/${channel.id}/edit`) | |
| - } | |
| - > | |
| - Edit | |
| - </Button> | |
| - <DeleteSalesChannelButton | |
| - channelId={channel.id} | |
| - disabled={channel.salesChannelTypeId === 1} | |
| - tooltip={ | |
| - channel.salesChannelTypeId === 1 | |
| - ? "In-store sales channels cannot be deleted" | |
| - : undefined | |
| - } | |
| - onDelete={() => { | |
| - queryClient.setQueryData( | |
| - queryKey, | |
| - (prev: ApiPageEntitySalesChannel) => { | |
| - return { | |
| - ...prev, | |
| - content: prev.content?.filter( | |
| - (c) => c.id !== channel.id, | |
| - ), | |
| - }; | |
| - }, | |
| - ); | |
| - }} | |
| - /> | |
| - </div> | |
| - </div> | |
| - </li> | |
| - ); | |
| - })} | |
| - </ul> | |
| - <StyledPaginationControls | |
| - page={page} | |
| - totalPages={salesChannels?.totalPages} | |
| - totalCount={salesChannels?.totalElements} | |
| - /> | |
| - | |
| - {/* Create Sales Channel Wizard */} | |
| - <CreateSalesChannelWizardV2 | |
| - isOpen={createDisclosure.isOpen} | |
| - onClose={createDisclosure.onClose} | |
| - onSave={(channel) => { | |
| - // Invalidate the query to refetch fresh data with complete sales channel info | |
| - void queryClient.invalidateQueries({ queryKey }); | |
| - }} | |
| - /> | |
| - </SettingsBlock> | |
| - ); | |
| -}; | |
| - | |
| -const DeleteSalesChannelButton: React.FC<{ | |
| - channelId: number; | |
| - onDelete: () => void; | |
| - disabled: boolean; | |
| - tooltip?: string; | |
| -}> = ({ channelId, onDelete, disabled, tooltip }) => { | |
| - const toast = useToast(); | |
| - const { mutateAsync: deleteSalesChannel, isPending: isLoading } = | |
| - useDeleteSalesChannel({ | |
| - mutation: { | |
| - onSuccess: (resp) => { | |
| - toast({ | |
| - status: "success", | |
| - title: "Sales channel deleted", | |
| - description: "Your sales channel has been deleted", | |
| - }); | |
| - }, | |
| - onError: (err: any) => { | |
| - if (isAxios400(err)) { | |
| - toast({ | |
| - title: "Error", | |
| - status: "error", | |
| - description: `Request failed. ${err}`, | |
| - }); | |
| - } else { | |
| - toast({ | |
| - title: "Error", | |
| - status: "error", | |
| - description: "An error occurred while deleting the sales channel", | |
| - }); | |
| - captureException(err); | |
| - } | |
| - }, | |
| - }, | |
| - }); | |
| - return ( | |
| - <TooltipProvider> | |
| - <Tooltip> | |
| - <TooltipTrigger> | |
| - <DeleteButtonWithWarning | |
| - isLoading={isLoading} | |
| - disabled={disabled} | |
| - onDelete={async () => { | |
| - await deleteSalesChannel({ | |
| - id: channelId, | |
| - }); | |
| - onDelete(); | |
| - }} | |
| - /> | |
| - </TooltipTrigger> | |
| - <TooltipContent> | |
| - <p>{tooltip}</p> | |
| - </TooltipContent> | |
| - </Tooltip> | |
| - </TooltipProvider> | |
| - ); | |
| -}; | |
| diff --git a/src/pages/Settings/Saleschannels/SalesChannelSettingsPanel.tsx b/src/pages/Settings/Saleschannels/SalesChannelSettingsPanel.tsx | |
| new file mode 100644 | |
| index 00000000..f2ae895b | |
| --- /dev/null | |
| +++ b/src/pages/Settings/Saleschannels/SalesChannelSettingsPanel.tsx | |
| @@ -0,0 +1,217 @@ | |
| +import { useDisclosure, useToast } from "@chakra-ui/react"; | |
| +import { captureException } from "@sentry/react"; | |
| +import { useQueryClient } from "@tanstack/react-query"; | |
| +import { StyledPaginationControls } from "components/common/StyledPaginationControls/StyledPaginationControls"; | |
| +import { DeleteButtonWithWarning } from "components/DeleteButtonWithWarning"; | |
| +import { SalesChannelBadge } from "components/SalesChannels/SalesChannelBadge"; | |
| +import { UpsertSalesChannelDialog } from "components/SalesChannels/UpsertSalesChannelDialog"; | |
| +import { SettingsBlock } from "components/SettingsComponents/SettingsBlock"; | |
| +import { Badge } from "components/ui/badge"; | |
| +import { Button } from "components/ui/button"; | |
| +import { | |
| + Tooltip, | |
| + TooltipContent, | |
| + TooltipProvider, | |
| + TooltipTrigger, | |
| +} from "components/ui/tooltip"; | |
| +import { useEntitySelected } from "context/EntityProvider"; | |
| +import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| +import { PlusIcon } from "lucide-react"; | |
| +import { useState } from "react"; | |
| +import { | |
| + ApiPageEntitySalesChannel, | |
| + EntitySalesChannel, | |
| + useDeleteSalesChannel, | |
| + useListSalesChannels, | |
| +} from "src/spring-generated"; | |
| +import { NumberParam, useQueryParams, withDefault } from "use-query-params"; | |
| +import { isAxios400 } from "utils/errors"; | |
| + | |
| +type SalesChannelSettingsPanelProps = {}; | |
| + | |
| +export const SalesChannelSettingsPanel: React.FC< | |
| + SalesChannelSettingsPanelProps | |
| +> = () => { | |
| + useDocumentTitle("Settings - Sales Channel"); | |
| + const [entity] = useEntitySelected(); | |
| + const queryClient = useQueryClient(); | |
| + const [{ page }] = useQueryParams({ | |
| + page: withDefault(NumberParam, 1), | |
| + }); | |
| + const { data: salesChannels, queryKey } = useListSalesChannels({ | |
| + entityIds: [entity.id], | |
| + page: page - 1, | |
| + size: 30, | |
| + }); | |
| + const [editingChannel, setEditingChannel] = useState<EntitySalesChannel>(); | |
| + const disclosure = useDisclosure({ | |
| + onClose: () => { | |
| + setEditingChannel(undefined); | |
| + }, | |
| + }); | |
| + | |
| + return ( | |
| + <SettingsBlock | |
| + flexGrow={1} | |
| + header={ | |
| + <div className="w-full flex flex-row justify-between"> | |
| + <h1 className="text-2xl font-bold">Sales Channels</h1> | |
| + <Button onClick={disclosure.onOpen}> | |
| + <PlusIcon className="w-4 h-4 mr-2" /> | |
| + New Sales Channel | |
| + </Button> | |
| + </div> | |
| + } | |
| + > | |
| + <ul className="space-y-4 w-full flex-grow flex flex-col"> | |
| + {salesChannels?.content?.map((channel) => ( | |
| + <li | |
| + key={channel.id} | |
| + className="flex items-center border-b justify-between p-2 rounded-md" | |
| + > | |
| + <div> | |
| + <div className="flex flex-row items-center gap-2"> | |
| + <h3 className="font-semibold">{channel.name}</h3> | |
| + <SalesChannelBadge salesChannel={channel} /> | |
| + </div> | |
| + {channel.accountId && ( | |
| + <p className="text-sm text-gray-600"> | |
| + Account ID: {channel.accountId} | |
| + </p> | |
| + )} | |
| + </div> | |
| + <div className="flex gap-2 items-center"> | |
| + <Badge>ID: {channel.id}</Badge> | |
| + <Badge variant={channel.active ? "successful" : "destructive"}> | |
| + {channel.active ? "Active" : "Inactive"} | |
| + </Badge> | |
| + <div className="flex flex-row gap-2"> | |
| + <Button | |
| + variant="outline" | |
| + disabled={channel.salesChannelTypeId === 1} | |
| + className="ml-4" | |
| + onClick={() => { | |
| + setEditingChannel(channel); | |
| + disclosure.onOpen(); | |
| + }} | |
| + > | |
| + Edit | |
| + </Button> | |
| + <DeleteSalesChannelButton | |
| + channelId={channel.id} | |
| + disabled={channel.salesChannelTypeId === 1} | |
| + tooltip={ | |
| + channel.salesChannelTypeId === 1 | |
| + ? "In-store sales channels cannot be deleted" | |
| + : undefined | |
| + } | |
| + onDelete={() => { | |
| + queryClient.setQueryData( | |
| + queryKey, | |
| + (prev: ApiPageEntitySalesChannel) => { | |
| + return { | |
| + ...prev, | |
| + content: prev.content?.filter( | |
| + (c) => c.id !== channel.id, | |
| + ), | |
| + }; | |
| + }, | |
| + ); | |
| + }} | |
| + /> | |
| + </div> | |
| + </div> | |
| + </li> | |
| + ))} | |
| + </ul> | |
| + <StyledPaginationControls | |
| + page={page} | |
| + totalPages={salesChannels?.totalPages} | |
| + totalCount={salesChannels?.totalElements} | |
| + /> | |
| + <UpsertSalesChannelDialog | |
| + key={editingChannel?.id} | |
| + isOpen={disclosure.isOpen} | |
| + onClose={disclosure.onClose} | |
| + channel={editingChannel} | |
| + onSave={(channel) => { | |
| + queryClient.setQueryData( | |
| + queryKey, | |
| + (prev: ApiPageEntitySalesChannel) => { | |
| + if (prev.content?.find((c) => c.id === channel.id)) { | |
| + return { | |
| + ...prev, | |
| + content: prev.content?.map((c) => | |
| + c.id === channel.id ? channel : c, | |
| + ), | |
| + }; | |
| + } | |
| + return { | |
| + ...prev, | |
| + content: [...(prev.content ?? []), channel], | |
| + }; | |
| + }, | |
| + ); | |
| + }} | |
| + /> | |
| + </SettingsBlock> | |
| + ); | |
| +}; | |
| + | |
| +const DeleteSalesChannelButton: React.FC<{ | |
| + channelId: number; | |
| + onDelete: () => void; | |
| + disabled: boolean; | |
| + tooltip?: string; | |
| +}> = ({ channelId, onDelete, disabled, tooltip }) => { | |
| + const toast = useToast(); | |
| + const { mutateAsync: deleteSalesChannel, isPending: isLoading } = | |
| + useDeleteSalesChannel({ | |
| + mutation: { | |
| + onSuccess: (resp) => { | |
| + toast({ | |
| + status: "success", | |
| + title: "Sales channel deleted", | |
| + description: "Your sales channel has been deleted", | |
| + }); | |
| + }, | |
| + onError: (err: any) => { | |
| + if (isAxios400(err)) { | |
| + toast({ | |
| + title: "Error", | |
| + status: "error", | |
| + description: `Request failed. ${err}`, | |
| + }); | |
| + } else { | |
| + toast({ | |
| + title: "Error", | |
| + status: "error", | |
| + description: "An error occurred while deleting the sales channel", | |
| + }); | |
| + captureException(err); | |
| + } | |
| + }, | |
| + }, | |
| + }); | |
| + return ( | |
| + <TooltipProvider> | |
| + <Tooltip> | |
| + <TooltipTrigger> | |
| + <DeleteButtonWithWarning | |
| + isLoading={isLoading} | |
| + disabled={disabled} | |
| + onDelete={async () => { | |
| + await deleteSalesChannel({ | |
| + id: channelId, | |
| + }); | |
| + onDelete(); | |
| + }} | |
| + /> | |
| + </TooltipTrigger> | |
| + <TooltipContent> | |
| + <p>{tooltip}</p> | |
| + </TooltipContent> | |
| + </Tooltip> | |
| + </TooltipProvider> | |
| + ); | |
| +}; | |
| diff --git a/src/pages/Settings/SettingsPage.tsx b/src/pages/Settings/SettingsPage.tsx | |
| index bea68f97..63243e0b 100644 | |
| --- a/src/pages/Settings/SettingsPage.tsx | |
| +++ b/src/pages/Settings/SettingsPage.tsx | |
| @@ -1,4 +1,3 @@ | |
| -import PGliteProvider from "components/pg-lite/PGliteProvider"; | |
| import { LoadingSpinner } from "components/ui/loading-spinner"; | |
| import { | |
| useEntitySelected, | |
| @@ -93,7 +92,7 @@ const RolesSettingsPanel = lazy(() => | |
| })), | |
| ); | |
| const SalesChannelSettingsPanel = lazy(() => | |
| - import("./SalesChannels/SalesChannelSettingsPanel").then((m) => ({ | |
| + import("./Saleschannels/SalesChannelSettingsPanel").then((m) => ({ | |
| default: m.SalesChannelSettingsPanel, | |
| })), | |
| ); | |
| @@ -373,9 +372,7 @@ const SettingsPage: React.FC<SettingsPageProps> = () => { | |
| link: "devices", | |
| component: ( | |
| <Suspense fallback={<SettingsLoadingFallback />}> | |
| - <PGliteProvider> | |
| - <DeviceManagementPanel key={entity?.id} /> | |
| - </PGliteProvider> | |
| + <DeviceManagementPanel key={entity?.id} /> | |
| </Suspense> | |
| ), | |
| requires: "entity/*:manage", | |
| diff --git a/src/pages/Settings/Tags/TagBadge.tsx b/src/pages/Settings/Tags/TagBadge.tsx | |
| index 2413a94d..ec082517 100644 | |
| --- a/src/pages/Settings/Tags/TagBadge.tsx | |
| +++ b/src/pages/Settings/Tags/TagBadge.tsx | |
| @@ -89,7 +89,6 @@ export const TagBadge: React.FC<TagBadgeProps> = ({ | |
| e.stopPropagation(); | |
| void deleteTag({} as never); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [deleteTag, onDelete, tag.id, containerRef], | |
| ); | |
| diff --git a/src/pages/Settings/Vendors/VendorSettingsPanel.tsx b/src/pages/Settings/Vendors/VendorSettingsPanel.tsx | |
| index 1bc63564..067f54fa 100644 | |
| --- a/src/pages/Settings/Vendors/VendorSettingsPanel.tsx | |
| +++ b/src/pages/Settings/Vendors/VendorSettingsPanel.tsx | |
| @@ -134,7 +134,6 @@ export const VendorSettingsPanel: React.FC = () => { | |
| if (data?.content?.length) { | |
| void preferredItemCount.refetch(); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [data?.content, page, preferredItemCount.refetch]); | |
| const { data: entityVendorCountMap, refetch: refetchCount } = | |
| diff --git a/src/pages/TransactionPage.tsx b/src/pages/TransactionPage.tsx | |
| index 1f9e3d8b..865116d6 100644 | |
| --- a/src/pages/TransactionPage.tsx | |
| +++ b/src/pages/TransactionPage.tsx | |
| @@ -35,17 +35,14 @@ import { | |
| } from "components/ui/tooltip"; | |
| import { useToast } from "components/ui/use-toast"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| -import { useUserAuth } from "context/AuthenticationContext/AuthenticationContext"; | |
| import { useRegisterProvider } from "context/RegisterProvider"; | |
| import { SalesPaymentProvider } from "context/Sales/SalesPaymentContext"; | |
| import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| import { useKeypress } from "hooks/useKeypress"; | |
| -import { useOrderItemDecisionUpdater } from "hooks/useOrderItemDecisionUpdater"; | |
| import { round } from "lodash-es"; | |
| import { Clock, LinkIcon, ScanLine, UserCheck2 } from "lucide-react"; | |
| import { useMemo, useState } from "react"; | |
| import { Link, useNavigate, useParams } from "react-router-dom"; | |
| -import { FulfillmentConfirmationModal } from "src/components/fulfillment/FulfillmentConfirmationModal"; | |
| import Loading from "src/components/Loading"; | |
| import { CustomerConfirmAlert } from "src/components/loyalty/CustomerConfirmAlert"; | |
| import { CustomerLookupModal } from "src/components/loyalty/CustomerLookupModal/CustomerLookupModal"; | |
| @@ -65,10 +62,6 @@ import { useGetLoyaltyCustomer } from "src/generated/hooks/useGetLoyaltyCustomer | |
| import { EntityConfigKey } from "src/generated/types/EntityConfigKey"; | |
| import { useEntityConfig } from "src/hooks/useEntityConfig"; | |
| import { cn } from "src/lib/utils"; | |
| -import { | |
| - useGetFulfillment, | |
| - useListOrderItemDecisions, | |
| -} from "src/phoenix-generated"; | |
| import { | |
| useGetEntitySalesChannelById, | |
| useHasDeleteAccess, | |
| @@ -96,7 +89,6 @@ const TransactionPage = () => { | |
| const { txId } = useParams(); | |
| const navigate = useNavigate(); | |
| const [entity] = useEntitySelected(); | |
| - const { user } = useUserAuth(); | |
| const { register } = useRegisterProvider(); | |
| const finishTransactionModal = useDisclosure(); | |
| const flagEnabled = useEntityConfig( | |
| @@ -118,8 +110,6 @@ const TransactionPage = () => { | |
| const { id: loyaltyProgramId } = useLoyaltyProgramIdOptional(); | |
| const [showDeleteTransactionAlert, setShowDeleteTransactionAlert] = | |
| useState(false); | |
| - const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set()); | |
| - const [showFulfillmentModal, setShowFulfillmentModal] = useState(false); | |
| const transactionRes = useGetTransactionById(+(txId ?? new Error("")), { | |
| query: { | |
| enabled: true, | |
| @@ -163,45 +153,6 @@ const TransactionPage = () => { | |
| }, | |
| }, | |
| ); | |
| - const { data: orderItemDecisions, refetch: orderItemDecisionsRefetch } = | |
| - useListOrderItemDecisions( | |
| - { | |
| - transaction_id: transactionDetail?.id ?? 0, | |
| - offset: 0, | |
| - limit: 100, | |
| - }, | |
| - { | |
| - query: { | |
| - enabled: !!transactionDetail?.id, | |
| - }, | |
| - }, | |
| - ); | |
| - const orderCanBeFulfilled = useMemo(() => { | |
| - return ( | |
| - (orderItemDecisions?.length ?? 0) > 0 && | |
| - orderItemDecisions?.every((decision) => decision.status !== "CREATED") | |
| - ); | |
| - }, [orderItemDecisions]); | |
| - console.log(orderItemDecisions); | |
| - const fulfillmentId = useMemo(() => { | |
| - const set = new Set( | |
| - orderItemDecisions?.map((decision) => decision.fulfillmentId), | |
| - ); | |
| - if (set.size > 1) { | |
| - captureException( | |
| - new Error("Multiple fulfillment ids found for transaction"), | |
| - ); | |
| - } | |
| - return set.values().next().value; | |
| - }, [orderItemDecisions]); | |
| - const { data: fulfillment, refetch: fulfillmentRefetch } = useGetFulfillment( | |
| - fulfillmentId ?? "", | |
| - { | |
| - query: { | |
| - enabled: !!fulfillmentId, | |
| - }, | |
| - }, | |
| - ); | |
| const { mutateAsync: linkCustomer } = useLinkCustomerToTransaction( | |
| transactionDetail?.id ?? 0, | |
| { | |
| @@ -234,57 +185,6 @@ const TransactionPage = () => { | |
| const { data: hasDeleteAccess } = useHasDeleteAccess(); | |
| - const { updateDecisions, isUpdating: isProcessingBulkAction } = | |
| - useOrderItemDecisionUpdater({ | |
| - onSuccess: () => { | |
| - // Refetch order item decisions after status update | |
| - void orderItemDecisionsRefetch(); | |
| - // Clear selection after successful bulk action | |
| - setSelectedRows(new Set()); | |
| - }, | |
| - }); | |
| - | |
| - // Row selection handlers | |
| - const handleRowSelect = (itemId: number, isSelected: boolean) => { | |
| - setSelectedRows((prev) => { | |
| - const newSet = new Set(prev); | |
| - if (isSelected) { | |
| - newSet.add(itemId); | |
| - } else { | |
| - newSet.delete(itemId); | |
| - } | |
| - return newSet; | |
| - }); | |
| - }; | |
| - | |
| - const handleSelectAll = (isSelected: boolean) => { | |
| - if (isSelected) { | |
| - const allItemIds = new Set( | |
| - transactionDetail?.transactionItems.map((item) => item.id) || [], | |
| - ); | |
| - setSelectedRows(allItemIds); | |
| - } else { | |
| - setSelectedRows(new Set()); | |
| - } | |
| - }; | |
| - | |
| - // Bulk action handlers | |
| - const handleBulkAction = async (status: "ACCEPTED" | "REJECTED") => { | |
| - if (selectedRows.size === 0 || !orderItemDecisions || !user?.uid) return; | |
| - | |
| - const decisionsToUpdate = orderItemDecisions | |
| - .filter((decision) => selectedRows.has(decision.transactionItemId)) | |
| - .map((decision) => ({ | |
| - decisionId: decision.id, | |
| - status, | |
| - userId: user.uid, | |
| - source: `${entity.id.toString()} register:${register.registerNumber?.toString() ?? "unknown"}`, | |
| - reason: `Bulk ${status.toLowerCase()} via cashier interface`, | |
| - })); | |
| - | |
| - await updateDecisions(decisionsToUpdate); | |
| - }; | |
| - | |
| useKeypress( | |
| new Map([ | |
| [ | |
| @@ -370,58 +270,9 @@ const TransactionPage = () => { | |
| </div> | |
| <div className="p-4 w-full h-full grid grid-cols-[3fr_1fr] gap-2 overflow-hidden"> | |
| <div className="grid grid-rows-[4fr_auto] gap-2 overflow-hidden"> | |
| - <Card | |
| - title="Items Summary" | |
| - headerActions={ | |
| - <> | |
| - {fulfillment && orderCanBeFulfilled && ( | |
| - <div className="flex items-center gap-2"> | |
| - <Button | |
| - size="sm" | |
| - disabled={!register.registerNumber} | |
| - onClick={() => setShowFulfillmentModal(true)} | |
| - > | |
| - {fulfillment.status === "COMPLETED" | |
| - ? "View Fulfillment" | |
| - : register.registerNumber | |
| - ? "Complete Order" | |
| - : "Select Register to Complete Order"} | |
| - </Button> | |
| - </div> | |
| - )} | |
| - {(orderItemDecisions?.length ?? 0) > 0 && | |
| - selectedRows.size > 0 ? ( | |
| - <div className="flex gap-2"> | |
| - <PermissionedButton | |
| - requires="orderitemdecision/*:update-status" | |
| - size="sm" | |
| - variant="outline" | |
| - disabled={isProcessingBulkAction} | |
| - onClick={() => handleBulkAction("ACCEPTED")} | |
| - > | |
| - Accept Selected ({selectedRows.size}) | |
| - </PermissionedButton> | |
| - <PermissionedButton | |
| - requires="orderitemdecision/*:update-status" | |
| - size="sm" | |
| - variant="destructive" | |
| - disabled={isProcessingBulkAction} | |
| - onClick={() => handleBulkAction("REJECTED")} | |
| - > | |
| - Reject Selected ({selectedRows.size}) | |
| - </PermissionedButton> | |
| - </div> | |
| - ) : undefined} | |
| - </> | |
| - } | |
| - > | |
| + <Card title="Items Summary"> | |
| <TransactionItemsTable | |
| items={transactionDetail.transactionItems} | |
| - orderItemDecisions={orderItemDecisions} | |
| - selectedRows={selectedRows} | |
| - onRowSelect={handleRowSelect} | |
| - onSelectAll={handleSelectAll} | |
| - onDecisionUpdated={() => orderItemDecisionsRefetch()} | |
| /> | |
| </Card> | |
| <Card title="Transaction Summary"> | |
| @@ -628,13 +479,6 @@ const TransactionPage = () => { | |
| resetCartToCurrentItems={() => undefined} | |
| salesChannel={salesChannel} | |
| payAfterConfirm={payAfterConfirm} | |
| - // Payment method functions (fallback implementations for transaction completion context) | |
| - paymentMethodTypeToPaymentMethod={{}} | |
| - calculateMethodsWithPrices={() => []} | |
| - findBestPaymentMethod={() => null} | |
| - isCalculatingBackgroundPaymentMethodTotals={false} | |
| - selectedSalesChannel={undefined} | |
| - setSkipSetItemsInCart={() => undefined} | |
| > | |
| <FinishTransacationPaymentModal | |
| isOpen={finishTransactionModal.isOpen} | |
| @@ -642,18 +486,6 @@ const TransactionPage = () => { | |
| /> | |
| </SalesPaymentProvider> | |
| )} | |
| - {fulfillmentId && ( | |
| - <FulfillmentConfirmationModal | |
| - isOpen={showFulfillmentModal} | |
| - onClose={() => setShowFulfillmentModal(false)} | |
| - fulfillmentId={fulfillmentId} | |
| - onSuccess={() => { | |
| - void transactionRes.refetch(); | |
| - void orderItemDecisionsRefetch(); | |
| - void fulfillmentRefetch(); | |
| - }} | |
| - /> | |
| - )} | |
| </> | |
| ); | |
| }; | |
| @@ -662,10 +494,9 @@ interface CardProps { | |
| title: string; | |
| children: React.ReactNode; | |
| className?: string; | |
| - headerActions?: React.ReactNode; | |
| } | |
| -const Card = ({ title, children, className, headerActions }: CardProps) => { | |
| +const Card = ({ title, children, className }: CardProps) => { | |
| return ( | |
| <div | |
| className={cn( | |
| @@ -673,9 +504,8 @@ const Card = ({ title, children, className, headerActions }: CardProps) => { | |
| className, | |
| )} | |
| > | |
| - <div className="bg-weak-100 border-b border-theme-gray-3 p-4 flex items-center justify-between"> | |
| + <div className="bg-weak-100 border-b border-theme-gray-3 p-4"> | |
| <p className="font-bold text-xl">{title}</p> | |
| - {headerActions} | |
| </div> | |
| <div className="px-4 py-4 overflow-y-auto h-full">{children}</div> | |
| </div> | |
| diff --git a/src/pages/TransactionsPage.tsx b/src/pages/TransactionsPage.tsx | |
| index 7d156607..95a97ea3 100644 | |
| --- a/src/pages/TransactionsPage.tsx | |
| +++ b/src/pages/TransactionsPage.tsx | |
| @@ -58,10 +58,6 @@ const ShowTransactions = { | |
| SUCCEEDED: [TransactionStatus.SUCCESS], | |
| REFUND: [TransactionStatus.REFUND], | |
| PENDING: [TransactionStatus.PENDING, TransactionStatus.CREATED], | |
| - // Status for transactions where order item decisions are pending | |
| - DECISION_REQUIRED: [TransactionStatus.SUCCESS], | |
| - // Status where fulfillment is pending | |
| - FULFILLMENT_REQUIRED: [TransactionStatus.SUCCESS], | |
| ALL: undefined, | |
| }; | |
| @@ -118,32 +114,17 @@ const TransactionsPage = (_: TransactionsPageProps) => { | |
| entityId: entity.id, | |
| page: page - 1, | |
| size: 20, | |
| - registerNumber: | |
| - selectedRegister && | |
| - showTransactions !== "DECISION_REQUIRED" && | |
| - showTransactions !== "FULFILLMENT_REQUIRED" | |
| - ? selectedRegister | |
| - : undefined, | |
| + registerNumber: selectedRegister ?? undefined, | |
| paymentForm: !!selectedPayForm ? [selectedPayForm] : undefined, | |
| salesChannelIds: | |
| selectedSalesChannels.length > 0 ? selectedSalesChannels : undefined, | |
| ...(enabledClosings && { closed: false }), | |
| sort: ["completedAt,desc", "createdDate,desc"], | |
| transactionStatus: ShowTransactions[showTransactions], | |
| - hasPendingDecisions: | |
| - showTransactions === "DECISION_REQUIRED" | |
| - ? true | |
| - : showTransactions === "FULFILLMENT_REQUIRED" | |
| - ? false | |
| - : undefined, | |
| - hasPendingFulfillment: | |
| - showTransactions === "FULFILLMENT_REQUIRED" ? true : undefined, | |
| - ...(!enabledClosings && | |
| - showTransactions !== "DECISION_REQUIRED" && | |
| - showTransactions !== "FULFILLMENT_REQUIRED" && { | |
| - startDate, | |
| - endDate, | |
| - }), | |
| + ...(!enabledClosings && { | |
| + startDate, | |
| + endDate, | |
| + }), | |
| }, | |
| { | |
| query: { | |
| @@ -258,7 +239,7 @@ const TransactionsPage = (_: TransactionsPageProps) => { | |
| > | |
| {Object.entries(ShowTransactions).map(([key]) => ( | |
| <RadioCard key={key} value={key}> | |
| - {key.replace("_", " ")} | |
| + {key} | |
| </RadioCard> | |
| ))} | |
| </RadioCardGroup> | |
| diff --git a/src/pages/gift_card/GiftCardReport.tsx b/src/pages/gift_card/GiftCardReport.tsx | |
| index 62a5f90f..8a8ad7af 100644 | |
| --- a/src/pages/gift_card/GiftCardReport.tsx | |
| +++ b/src/pages/gift_card/GiftCardReport.tsx | |
| @@ -170,7 +170,6 @@ const GiftCardReport = () => { | |
| isLoading.setFalse(); | |
| } | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| setStatus, | |
| giftCardApi, | |
| diff --git a/src/pages/inventory_transfer/InventoryTransfersPage.tsx b/src/pages/inventory_transfer/InventoryTransfersPage.tsx | |
| index a4da390f..7f823191 100644 | |
| --- a/src/pages/inventory_transfer/InventoryTransfersPage.tsx | |
| +++ b/src/pages/inventory_transfer/InventoryTransfersPage.tsx | |
| @@ -115,7 +115,6 @@ export const useListInventoryTransfersHook = () => { | |
| number: data.page.number + 1, | |
| }); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [data]); | |
| return { | |
| @@ -364,7 +363,6 @@ const InventoryTransfersPage = () => { | |
| }, | |
| }), | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| allPossibleEntities, | |
| entityId, | |
| diff --git a/src/pages/inventory_transfer/PrintInventoryTransferPage.tsx b/src/pages/inventory_transfer/PrintInventoryTransferPage.tsx | |
| index e5449b1d..0b612574 100644 | |
| --- a/src/pages/inventory_transfer/PrintInventoryTransferPage.tsx | |
| +++ b/src/pages/inventory_transfer/PrintInventoryTransferPage.tsx | |
| @@ -96,7 +96,11 @@ const PrintInventoryTransferPage: React.FC<PrintInvoicePageProps> = ({}) => { | |
| role="button" | |
| tabIndex={0} | |
| onClick={() => { | |
| - if (hasPermission(`item/*:read`)) { | |
| + if ( | |
| + hasPermission( | |
| + `item/*:read`, | |
| + ) | |
| + ) { | |
| setSelectedItem(row.original.entityItemSent); | |
| } | |
| }} | |
| @@ -161,7 +165,6 @@ const PrintInventoryTransferPage: React.FC<PrintInvoicePageProps> = ({}) => { | |
| footer: SumFooterCell, | |
| }), | |
| ]; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [inventoryTransfer]); | |
| if (!id) { | |
| @@ -186,7 +189,6 @@ const PrintInventoryTransferPage: React.FC<PrintInvoicePageProps> = ({}) => { | |
| </SkeletonText> | |
| <SkeletonText isLoaded={!!inventoryTransfer}> | |
| <HStack w="100%"> | |
| - ur | |
| <Heading size="md"> | |
| { | |
| allPossibleEntities.find( | |
| diff --git a/src/pages/inventory_transfer/edit/InventoryTransferEditTable.tsx b/src/pages/inventory_transfer/edit/InventoryTransferEditTable.tsx | |
| index 055791ef..4a8fe0bb 100644 | |
| --- a/src/pages/inventory_transfer/edit/InventoryTransferEditTable.tsx | |
| +++ b/src/pages/inventory_transfer/edit/InventoryTransferEditTable.tsx | |
| @@ -441,7 +441,6 @@ const InventoryTablePageTableInner = ( | |
| setAddingItem(true); | |
| } | |
| }; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| inventoryTransfer.id, | |
| postInventoryTransferItem, | |
| @@ -783,7 +782,6 @@ const InventoryTablePageTableInner = ( | |
| }, | |
| }, | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [ | |
| canEditCellRef, | |
| hideColumns, | |
| diff --git a/src/pages/invoices/InvoicePage/InvoiceCommonHeader.tsx b/src/pages/invoices/InvoicePage/InvoiceCommonHeader.tsx | |
| index 05162421..cad7942d 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoiceCommonHeader.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoiceCommonHeader.tsx | |
| @@ -18,12 +18,14 @@ import { GridApi } from "ag-grid-community"; | |
| import { type SelectInstance } from "chakra-react-select"; | |
| import { SavingIndicator } from "components/common/SavingIndicator/SavingIndicator"; | |
| import { InvoiceStatusTag } from "components/invoices/InvoiceStatusTag"; | |
| +import { captureException } from "config/sentry/TransformitySentry"; | |
| import { useInvoiceContext } from "context/InvoiceContext"; | |
| import { format } from "date-fns"; | |
| import { useAllVendors } from "hooks/useAllVendors"; | |
| -import { ExternalLink, SearchIcon, UnfoldHorizontal, X } from "lucide-react"; | |
| +import { ExternalLink, FileText, SearchIcon, X } from "lucide-react"; | |
| import React, { useMemo, useRef } from "react"; | |
| import { Link } from "react-router-dom"; | |
| +import { useGetDownloadAssetLink } from "src/spring-generated/hooks"; | |
| import { CreateItemModalRefProps } from "./InvoicePage"; | |
| import InvoiceSearchAddItemSelect from "./InvoiceSearchAddItemSelect"; | |
| import { InvoiceTotal } from "./InvoiceTotal"; | |
| @@ -37,7 +39,6 @@ interface InvoiceCommonHeaderProps { | |
| setActiveStep: (step: number) => void; | |
| invoiceTableGridApiRef: React.RefObject<GridApi | undefined>; | |
| onAddItem?: (item: EntityItemDetail | undefined) => void; | |
| - onComparePdf?: () => void; | |
| createItemModalRef: React.RefObject<CreateItemModalRefProps | null>; | |
| asyncSelectInputRef: React.RefObject<SelectInstance<any | null>>; | |
| } | |
| @@ -49,12 +50,12 @@ export const InvoiceCommonHeader: React.FC<InvoiceCommonHeaderProps> = ({ | |
| setActiveStep, | |
| invoiceTableGridApiRef, | |
| onAddItem = () => {}, | |
| - onComparePdf = () => {}, | |
| createItemModalRef, | |
| asyncSelectInputRef, | |
| }) => { | |
| const inputRef = useRef<HTMLInputElement | null>(null); | |
| const { sums, isLoading, savingItemIds, isEditing } = useInvoiceContext(); | |
| + const downloadAssetLinkMutation = useGetDownloadAssetLink(); | |
| const onChange = (value: string) => { | |
| invoiceTableGridApiRef.current?.setGridOption("quickFilterText", value); | |
| @@ -64,16 +65,35 @@ export const InvoiceCommonHeader: React.FC<InvoiceCommonHeaderProps> = ({ | |
| return ((sums?.totalCost ?? 0) + (invoice?.other ?? 0)).toFixed(2); | |
| }, [sums?.totalCost, invoice.other]); | |
| + const handleDownloadPDF = async () => { | |
| + if (!invoice.cohortAssetId) return; | |
| + | |
| + try { | |
| + const downloadUrl = await downloadAssetLinkMutation.mutateAsync({ | |
| + data: { | |
| + cohortAssetId: invoice.cohortAssetId, | |
| + entityId: invoice.entityId, | |
| + }, | |
| + }); | |
| + | |
| + // Open the PDF in a new tab | |
| + window.open(downloadUrl, "_blank"); | |
| + } catch (error) { | |
| + console.error("Error downloading PDF:", error); | |
| + captureException(error); | |
| + } | |
| + }; | |
| + | |
| return ( | |
| - <div className="flex flex-col gap-y-4 w-full"> | |
| + <div className="flex flex-col gap-y-4 w-[95vw]"> | |
| <HStack | |
| alignItems="start" | |
| spacing={0} | |
| - w="100%" | |
| + w={"95vw"} | |
| justifyContent={"space-between"} | |
| gap={2} | |
| > | |
| - <Flex gap={3} alignItems={"center"} wrap={"wrap"}> | |
| + <Flex gap={3} flexShrink={0} alignItems={"center"}> | |
| <HStack | |
| textColor="gray.600" | |
| padding={"0.5rem 0.75rem"} | |
| @@ -101,6 +121,18 @@ export const InvoiceCommonHeader: React.FC<InvoiceCommonHeaderProps> = ({ | |
| <InvoiceStatusTag status={invoice.status} /> | |
| </HStack> | |
| <UpdateInvoiceDialog invoice={invoice} /> | |
| + {invoice.cohortAssetId && ( | |
| + <Button | |
| + variant="outline" | |
| + className="px-2" | |
| + aria-label="Download PDF" | |
| + onClick={handleDownloadPDF} | |
| + isLoading={downloadAssetLinkMutation.isPending} | |
| + > | |
| + <FileText className="size-5 text-theme-gray-1" /> | |
| + <ExternalLink className="size-4 text-theme-gray-1" /> | |
| + </Button> | |
| + )} | |
| {activeStep === 0 && ( | |
| <Popover placement="bottom-start" initialFocusRef={inputRef}> | |
| <PopoverTrigger> | |
| @@ -155,12 +187,6 @@ export const InvoiceCommonHeader: React.FC<InvoiceCommonHeaderProps> = ({ | |
| saving={savingItemIds.size > 0 || isLoading} | |
| savingCount={savingItemIds.size} | |
| /> | |
| - {activeStep === 0 && invoice.cohortAssetId && ( | |
| - <Button variant="outline" className="px-2" onClick={onComparePdf}> | |
| - <UnfoldHorizontal className="size-5 mr-1 text-blue-500" />{" "} | |
| - <span className="text-blue-500">Compare PDF</span> | |
| - </Button> | |
| - )} | |
| </Flex> | |
| <Flex gap={"1.5rem"}> | |
| <div className="flex items-center gap-x-2"> | |
| diff --git a/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPage.tsx b/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPage.tsx | |
| index d1ccb116..6283bc55 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPage.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPage.tsx | |
| @@ -102,7 +102,7 @@ export const InvoiceEditPage: React.FC<InvoiceEditPageProps> = forwardRef( | |
| return ( | |
| <> | |
| - <Card w="100%" minH={0} flexGrow={1} border={"none"} shadow={"none"}> | |
| + <Card w="95vw" minH={0} flexGrow={1} border={"none"} shadow={"none"}> | |
| <InvoicePageTable | |
| isEditing={isEditing} | |
| setLinkingItem={setLinkingItem} | |
| @@ -116,7 +116,6 @@ export const InvoiceEditPage: React.FC<InvoiceEditPageProps> = forwardRef( | |
| invoiceTableGridApiRef={invoiceTableGridApiRef} | |
| /> | |
| </Card> | |
| - | |
| <SwapItemModal | |
| {...linkItemDisclosure} | |
| linkingInvoiceItem={`${linkingItem?.invoiceItemDescription || ""} ${linkingItem?.sku ? "(" + linkingItem.sku + ")" : ""}`} | |
| diff --git a/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPageTable.tsx b/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPageTable.tsx | |
| index c6681976..3e34365a 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPageTable.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoiceEditStep/InvoiceEditPageTable.tsx | |
| @@ -541,7 +541,6 @@ const InvoicePageTableInner = ( | |
| } | |
| }, | |
| }), | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [asyncSelectInputRef, invoice.cohortVendorId, queryClient, setAddingItem], | |
| ); | |
| @@ -703,7 +702,6 @@ const InvoicePageTableInner = ( | |
| searchControlActiveStyles(); | |
| }; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| invoice.id, | |
| linkItemDisclosure, | |
| @@ -933,7 +931,6 @@ const InvoicePageTableInner = ( | |
| hide: true, | |
| }, | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [], | |
| ); | |
| @@ -1130,7 +1127,6 @@ const InvoicePageTableInner = ( | |
| api.removeEventListener("rowDataUpdated", applyFocusToRenderedRows); | |
| }; | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [focusedCell]); | |
| const removeHoverClasses = () => { | |
| diff --git a/src/pages/invoices/InvoicePage/InvoiceFooter.tsx b/src/pages/invoices/InvoicePage/InvoiceFooter.tsx | |
| index f157c7c7..f67fe132 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoiceFooter.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoiceFooter.tsx | |
| @@ -72,7 +72,7 @@ export const InvoiceFooter: React.FC<InvoiceFooterProps> = ({ | |
| return ( | |
| <Grid | |
| - w="100%" | |
| + w={"95vw"} | |
| justifyContent={"space-between"} | |
| gridTemplateColumns={"1fr 1fr"} | |
| > | |
| diff --git a/src/pages/invoices/InvoicePage/InvoicePage.tsx b/src/pages/invoices/InvoicePage/InvoicePage.tsx | |
| index 04d39339..223e3bcd 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoicePage.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoicePage.tsx | |
| @@ -10,23 +10,17 @@ import { | |
| import { Stack, UseDisclosureProps, useSteps } from "@chakra-ui/react"; | |
| import { GridApi } from "ag-grid-community"; | |
| import { SelectInstance } from "chakra-react-select"; | |
| -import { captureException } from "config/sentry/TransformitySentry"; | |
| import { InvoiceProvider } from "context/InvoiceContext"; | |
| import { useDocumentTitle } from "hooks/useDocumentTitle"; | |
| import { useEffect, useMemo, useRef, useState } from "react"; | |
| -import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; | |
| import { useNavigate, useParams, useSearchParams } from "react-router-dom"; | |
| -import { | |
| - ItemSearchResponseDto, | |
| - useGetDownloadAssetLink, | |
| -} from "src/spring-generated"; | |
| +import { ItemSearchResponseDto } from "src/spring-generated"; | |
| import Loading from "../../../components/Loading"; | |
| import { NavBarPlain } from "../../../components/navbar/NavBarPlain"; | |
| import { useAllVendors } from "../../../hooks/useAllVendors"; | |
| import { InvoiceCommonHeader } from "./InvoiceCommonHeader"; | |
| import { InvoiceFooter } from "./InvoiceFooter"; | |
| import { invoicePageSteps } from "./InvoicePageStepper"; | |
| -import { InvoicePdfDrawer } from "./InvoicePdfDrawer"; | |
| export interface AddItemRefProps { | |
| addItem?: ( | |
| @@ -59,9 +53,6 @@ const InvoicePage = () => { | |
| const { invoice, setInvoice, refetch } = useInvoice({ id }); | |
| const [searchParams, setSearchParams] = useSearchParams(); | |
| const { toast } = useToast(); | |
| - const downloadAssetLinkMutation = useGetDownloadAssetLink(); | |
| - const [pdfUrl, setPdfUrl] = useState<string>(""); | |
| - const [openPdfViewer, setOpenPdfViewer] = useState(false); | |
| // Call useListInvoices at component level with enabled option | |
| const { data: searchInvoice } = useListInvoices( | |
| @@ -98,7 +89,6 @@ const InvoicePage = () => { | |
| title: "Duplicate invoices found", | |
| description: `There are multiple invoices with the same invoice id. Other invoice IDs: ${otherInvoiceIds}`, | |
| variant: "destructive", | |
| - duration: Infinity, | |
| }); | |
| } | |
| }, [searchInvoices, invoice?.id, toast]); | |
| @@ -125,30 +115,6 @@ const InvoicePage = () => { | |
| } | |
| }; | |
| - const handleComparePdf = () => { | |
| - if (!invoice) return; | |
| - if (!invoice.cohortAssetId) return; | |
| - | |
| - setOpenPdfViewer(true); | |
| - void downloadAssetLinkMutation | |
| - .mutateAsync({ | |
| - data: { | |
| - cohortAssetId: invoice.cohortAssetId, | |
| - entityId: invoice.entityId, | |
| - }, | |
| - }) | |
| - .then((scannedPdfUrl) => { | |
| - setPdfUrl(scannedPdfUrl); | |
| - }) | |
| - .catch((err) => { | |
| - captureException(err); | |
| - }); | |
| - }; | |
| - | |
| - const handleClosePdfViewer = () => { | |
| - setOpenPdfViewer(false); | |
| - }; | |
| - | |
| useEffect(() => { | |
| if (searchParams.has("step")) { | |
| const step = Number(searchParams.get("step")); | |
| @@ -178,72 +144,43 @@ const InvoicePage = () => { | |
| paddingBottom={10} | |
| > | |
| <NavBarPlain flexClassNames="!bg-[#F8F9FC] border-b border-b-theme-gray-3" /> | |
| - <div className="w-full px-6 flex-1 max-h-full flex flex-col"> | |
| - <PanelGroup direction="horizontal" className="flex h-full flex-1"> | |
| - <Panel | |
| - defaultSize={75} | |
| - minSize={50} | |
| - className="flex flex-col gap-3 pr-4" | |
| - > | |
| - <InvoiceCommonHeader | |
| - vendors={vendors} | |
| - invoice={invoice} | |
| - activeStep={activeStep} | |
| - setActiveStep={setActiveStep} | |
| - invoiceTableGridApiRef={invoiceTableGridApiRef} | |
| - onAddItem={addItemToGrid as any} | |
| - createItemModalRef={createItemModalRef} | |
| - asyncSelectInputRef={asyncSelectInputRef} | |
| - onComparePdf={handleComparePdf} | |
| - /> | |
| - {/* @ts-expect-error */} | |
| - {invoicePageSteps[activeStep].content({ | |
| - setActiveStep, | |
| - vendors: vendors ?? new Map(), | |
| - addItemRef: addItemRef, | |
| - createItemModalRef: createItemModalRef, | |
| - asyncSelectInputRef: asyncSelectInputRef, | |
| - invoiceTableGridApiRef: invoiceTableGridApiRef, | |
| - })} | |
| - <InvoiceFooter | |
| - activeStep={activeStep} | |
| - onStepChange={(step, ctx) => { | |
| - if ( | |
| - step === 1 && | |
| - ctx.invoice.status !== InvoiceStatus.COMPLETE | |
| - ) { | |
| - void ctx.saveInvoice({ | |
| - ...ctx.invoice, | |
| - status: InvoiceStatus.ITEM_MANAGEMENT, | |
| - }); | |
| - } | |
| - if (step === -1) { | |
| - navigate(-1); | |
| - } else { | |
| - setActiveStep(step); | |
| - searchParams.set("step", step.toString()); | |
| - setSearchParams(searchParams); | |
| - } | |
| - }} | |
| - /> | |
| - </Panel> | |
| - | |
| - {openPdfViewer && ( | |
| - <> | |
| - <PanelResizeHandle className="w-2 bg-gray-200 hover:bg-blue-300 transition-colors cursor-col-resize flex items-center justify-center"> | |
| - <div className="w-0.5 h-8 bg-gray-400 rounded-full"></div> | |
| - </PanelResizeHandle> | |
| - <InvoicePdfDrawer | |
| - open={openPdfViewer} | |
| - pdfUrl={pdfUrl} | |
| - invoiceNumber={invoice.invoiceId} | |
| - invoiceId={invoice.id} | |
| - onClose={handleClosePdfViewer} | |
| - /> | |
| - </> | |
| - )} | |
| - </PanelGroup> | |
| - </div> | |
| + <InvoiceCommonHeader | |
| + vendors={vendors} | |
| + invoice={invoice} | |
| + activeStep={activeStep} | |
| + setActiveStep={setActiveStep} | |
| + invoiceTableGridApiRef={invoiceTableGridApiRef} | |
| + onAddItem={addItemToGrid as any} | |
| + createItemModalRef={createItemModalRef} | |
| + asyncSelectInputRef={asyncSelectInputRef} | |
| + /> | |
| + {/* @ts-expect-error */} | |
| + {invoicePageSteps[activeStep].content({ | |
| + setActiveStep, | |
| + vendors: vendors ?? new Map(), | |
| + addItemRef: addItemRef, | |
| + createItemModalRef: createItemModalRef, | |
| + asyncSelectInputRef: asyncSelectInputRef, | |
| + invoiceTableGridApiRef: invoiceTableGridApiRef, | |
| + })} | |
| + <InvoiceFooter | |
| + activeStep={activeStep} | |
| + onStepChange={(step, ctx) => { | |
| + if (step === 1 && ctx.invoice.status !== InvoiceStatus.COMPLETE) { | |
| + void ctx.saveInvoice({ | |
| + ...ctx.invoice, | |
| + status: InvoiceStatus.ITEM_MANAGEMENT, | |
| + }); | |
| + } | |
| + if (step === -1) { | |
| + navigate(-1); | |
| + } else { | |
| + setActiveStep(step); | |
| + searchParams.set("step", step.toString()); | |
| + setSearchParams(searchParams); | |
| + } | |
| + }} | |
| + /> | |
| </Stack> | |
| </InvoiceProvider> | |
| ); | |
| diff --git a/src/pages/invoices/InvoicePage/InvoicePdfDrawer.tsx b/src/pages/invoices/InvoicePage/InvoicePdfDrawer.tsx | |
| deleted file mode 100644 | |
| index 27abf06e..00000000 | |
| --- a/src/pages/invoices/InvoicePage/InvoicePdfDrawer.tsx | |
| +++ /dev/null | |
| @@ -1,69 +0,0 @@ | |
| -import { X } from "lucide-react"; | |
| -import React, { memo, useState } from "react"; | |
| -import { Panel } from "react-resizable-panels"; | |
| - | |
| -interface InvoicePdfDrawerProps { | |
| - pdfUrl: string; | |
| - invoiceNumber?: string; | |
| - invoiceId?: number; | |
| - open: boolean; | |
| - onClose: () => void; | |
| -} | |
| - | |
| -export const InvoicePdfDrawer: React.FC<InvoicePdfDrawerProps> = memo( | |
| - ({ pdfUrl, invoiceNumber, invoiceId, open, onClose }) => { | |
| - const [isLoading, setIsLoading] = useState(true); | |
| - | |
| - const handleIframeLoad = () => { | |
| - setIsLoading(false); | |
| - }; | |
| - | |
| - const handleIframeError = () => { | |
| - setIsLoading(false); | |
| - }; | |
| - | |
| - if (!open) return null; | |
| - | |
| - return ( | |
| - <Panel | |
| - defaultSize={25} | |
| - minSize={15} | |
| - maxSize={50} | |
| - className="flex flex-col rounded-md overflow-hidden bg-white border-l border-gray-200" | |
| - > | |
| - {/* Header */} | |
| - {/* Header */} | |
| - <div className="flex flex-row items-center justify-between p-4 border-b bg-gray-50"> | |
| - <div className="flex items-center space-x-2"> | |
| - <h3 className="text-lg font-semibold text-gray-900">PDF Viewer</h3> | |
| - </div> | |
| - <div> | |
| - <X | |
| - className="w-6 h-6 text-theme-gray-1 cursor-pointer hover:text-gray-700 transition-colors" | |
| - onClick={onClose} | |
| - /> | |
| - </div> | |
| - </div> | |
| - | |
| - {/* Content */} | |
| - <div className="flex-1 relative bg-gray-100 rounded-md"> | |
| - {isLoading && ( | |
| - <div className="absolute inset-0 flex items-center justify-center bg-white z-10"> | |
| - <div className="flex flex-col items-center space-y-2"> | |
| - <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div> | |
| - <p className="text-sm text-gray-600">Loading Invoice...</p> | |
| - </div> | |
| - </div> | |
| - )} | |
| - <iframe | |
| - src={pdfUrl} | |
| - className="w-full h-full border-0" | |
| - title={`Invoice Preview ${invoiceNumber || ""}`} | |
| - onLoad={handleIframeLoad} | |
| - onError={handleIframeError} | |
| - /> | |
| - </div> | |
| - </Panel> | |
| - ); | |
| - }, | |
| -); | |
| diff --git a/src/pages/invoices/InvoicePage/InvoicePricingStep/InvoicePricingPage.tsx b/src/pages/invoices/InvoicePage/InvoicePricingStep/InvoicePricingPage.tsx | |
| index 8354126f..3706d162 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoicePricingStep/InvoicePricingPage.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoicePricingStep/InvoicePricingPage.tsx | |
| @@ -139,7 +139,7 @@ export const InvoicePricingPage: React.FC<InvoicePricingPageProps> = () => { | |
| if (!sums) return null; | |
| return ( | |
| - <Card w="100%" border={"none"} shadow={"none"} flex={1} overflow="hidden"> | |
| + <Card w="95vw" border={"none"} shadow={"none"} flex={1} overflow="hidden"> | |
| <CardHeader px={0}> | |
| <HStack overflow="auto" justifyContent={"space-between"}> | |
| <Stack | |
| diff --git a/src/pages/invoices/InvoicePage/InvoiceSearchAddItemSelect.tsx b/src/pages/invoices/InvoicePage/InvoiceSearchAddItemSelect.tsx | |
| index 89efaf61..f3230c97 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoiceSearchAddItemSelect.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoiceSearchAddItemSelect.tsx | |
| @@ -390,7 +390,6 @@ export const InvoiceSearchAddItemSelect = ( | |
| ref.current?.onInputBlur(props); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [autoSelectSingleResult, searchResults]); | |
| // const debouncedChangeHandler = useMemo( | |
| diff --git a/src/pages/invoices/InvoicePage/InvoiceTotal.tsx b/src/pages/invoices/InvoicePage/InvoiceTotal.tsx | |
| index a3260ebc..15367dc1 100644 | |
| --- a/src/pages/invoices/InvoicePage/InvoiceTotal.tsx | |
| +++ b/src/pages/invoices/InvoicePage/InvoiceTotal.tsx | |
| @@ -43,8 +43,6 @@ export const InvoiceTotal: React.FC<InvoiceTotalProps> = ({ invoice }) => { | |
| <Tooltip | |
| label="Invoice Total does not match sum of item subtotals + other." | |
| isDisabled={totalDiff === 0} | |
| - placement="bottom-end" | |
| - offset={[0, 10]} | |
| > | |
| <VStack gap={"0.25rem"} alignItems={"flex-start"}> | |
| <HStack> | |
| diff --git a/src/pages/invoices/InvoicePage/SuspiciousPriceReviewModal.tsx b/src/pages/invoices/InvoicePage/SuspiciousPriceReviewModal.tsx | |
| index a3b49e58..9cbd5c2d 100644 | |
| --- a/src/pages/invoices/InvoicePage/SuspiciousPriceReviewModal.tsx | |
| +++ b/src/pages/invoices/InvoicePage/SuspiciousPriceReviewModal.tsx | |
| @@ -81,8 +81,8 @@ export const SuspiciousPriceReviewModal: React.FC< | |
| <div className="space-y-4"> | |
| <p className="text-orange-600 text-sm"> | |
| The following items have suspicious net unit costs that vary greatly | |
| - from their previous cost. Please review the net unit costs and | |
| - confirm they are correct. | |
| + from their previous cost. Please review the net unit costs and confirm | |
| + they are correct. | |
| </p> | |
| <Table> | |
| diff --git a/src/pages/invoices/InvoicesPage/UploadInvoiceModal.tsx b/src/pages/invoices/InvoicesPage/UploadInvoiceModal.tsx | |
| index 902e9c5d..48e4f421 100644 | |
| --- a/src/pages/invoices/InvoicesPage/UploadInvoiceModal.tsx | |
| +++ b/src/pages/invoices/InvoicesPage/UploadInvoiceModal.tsx | |
| @@ -118,7 +118,6 @@ export const UploadInvoiceModal = ({ | |
| } finally { | |
| setIsUploading(false); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| createInvoice, | |
| disclosure, | |
| diff --git a/src/pages/item/ItemListDetailPage.tsx b/src/pages/item/ItemListDetailPage.tsx | |
| index 2683afa9..be94c93f 100644 | |
| --- a/src/pages/item/ItemListDetailPage.tsx | |
| +++ b/src/pages/item/ItemListDetailPage.tsx | |
| @@ -484,7 +484,6 @@ const ItemListDetailPage = () => { | |
| }, | |
| }), | |
| ], | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [handleSaveItem, isUpdatePending, getOriginalItem, isDeletePending], | |
| ); | |
| diff --git a/src/pages/item/ItemListsPage.tsx b/src/pages/item/ItemListsPage.tsx | |
| index fee423d0..3f85cac5 100644 | |
| --- a/src/pages/item/ItemListsPage.tsx | |
| +++ b/src/pages/item/ItemListsPage.tsx | |
| @@ -140,7 +140,6 @@ const ItemListsPage = () => { | |
| number: itemListsResults.page.number + 1, | |
| })); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [isSuccess, itemListsResults?.page.number, setPageState]); | |
| const setName = useCallback( | |
| diff --git a/src/pages/item/ItemSearchPage.tsx b/src/pages/item/ItemSearchPage.tsx | |
| index 7691724b..960cb143 100644 | |
| --- a/src/pages/item/ItemSearchPage.tsx | |
| +++ b/src/pages/item/ItemSearchPage.tsx | |
| @@ -731,7 +731,6 @@ const ItemSearchPage = () => { | |
| setValue("tags", tags.flat()); | |
| }); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [queryClient, reset, setValue]); | |
| const handleTextInput = useCallback( | |
| diff --git a/src/pages/item/ItemStateMinReport.tsx b/src/pages/item/ItemStateMinReport.tsx | |
| index 78128ff2..32c19ae7 100644 | |
| --- a/src/pages/item/ItemStateMinReport.tsx | |
| +++ b/src/pages/item/ItemStateMinReport.tsx | |
| @@ -78,7 +78,6 @@ const ItemStateMinReport = () => { | |
| (nextStateMin && item.price < nextStateMin) | |
| ); | |
| }); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [stateMinViolations, currMonth, currYear, nextMonth]); | |
| const { mutateAsync: patchItem } = usePatchItem(); | |
| @@ -214,7 +213,6 @@ const ItemStateMinReport = () => { | |
| }, | |
| ), | |
| ]; | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [ | |
| stateMinViolations, | |
| columnHelper, | |
| diff --git a/src/pages/loyalty/CustomerLoyaltyProfile.tsx b/src/pages/loyalty/CustomerLoyaltyProfile.tsx | |
| index f56e013d..f80aa4d3 100644 | |
| --- a/src/pages/loyalty/CustomerLoyaltyProfile.tsx | |
| +++ b/src/pages/loyalty/CustomerLoyaltyProfile.tsx | |
| @@ -79,7 +79,6 @@ const CustomerLoyaltyProfile: React.FC<CustomerLoyaltyProfileProps> = ({}) => { | |
| queryClient.invalidateQueries({ | |
| queryKey: transactionsTableQueryKey.current, | |
| }); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [pointsTableQueryKey, transactionsTableQueryKey, queryClient]); | |
| const { data: houseAccountTotal } = | |
| diff --git a/src/pages/marketing/components/CampaignHeader.tsx b/src/pages/marketing/components/CampaignHeader.tsx | |
| index c9866b59..09495bee 100644 | |
| --- a/src/pages/marketing/components/CampaignHeader.tsx | |
| +++ b/src/pages/marketing/components/CampaignHeader.tsx | |
| @@ -64,7 +64,6 @@ export const CampaignHeader: React.FC<CampaignHeaderProps> = ({ | |
| // Proceed with status change | |
| await performStatusUpdate(active); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [campaign, triggersResponse?.content?.length], | |
| ); | |
| diff --git a/src/pages/marketing/components/CampaignParticipantsTab.tsx b/src/pages/marketing/components/CampaignParticipantsTab.tsx | |
| index 84d5218d..553e8f4d 100644 | |
| --- a/src/pages/marketing/components/CampaignParticipantsTab.tsx | |
| +++ b/src/pages/marketing/components/CampaignParticipantsTab.tsx | |
| @@ -12,11 +12,10 @@ import { useToast } from "@/components/ui/use-toast"; | |
| import { useDebouncedCallback } from "@tanstack/react-pacer"; | |
| import { captureException } from "config/sentry/TransformitySentry"; | |
| import { Activity, Eye, Users } from "lucide-react"; | |
| -import type React from "react"; | |
| -import { useCallback, useEffect, useRef, useState } from "react"; | |
| +import React, { useCallback, useEffect, useRef, useState } from "react"; | |
| import { | |
| CustomerFilterForm, | |
| - type CustomerFilterFormRef, | |
| + CustomerFilterFormRef, | |
| CustomerList, | |
| } from "src/components/CustomerFilter"; | |
| import { CsvParticipantUpload } from "src/components/marketing/CsvParticipantUpload"; | |
| @@ -27,11 +26,11 @@ import { | |
| useGetCustomerFilter, | |
| useUpdateCampaign, | |
| } from "src/spring-generated/hooks"; | |
| -import type { Campaign } from "src/spring-generated/types"; | |
| +import { Campaign } from "src/spring-generated/types"; | |
| import { CustomerFilterSummary } from "./shared/CustomerFilterDisplay"; | |
| import { | |
| CustomerSelectionModeSelector, | |
| - type SelectionMode, | |
| + SelectionMode, | |
| } from "./shared/CustomerSelectionModeSelector"; | |
| interface CampaignParticipantsTabProps { | |
| @@ -48,9 +47,10 @@ export const CampaignParticipantsTab: React.FC< | |
| const [selectionMode, setSelectionMode] = useState<SelectionMode>("all"); | |
| const [isDrawerOpen, setIsDrawerOpen] = useState(false); | |
| const customerFilterFormRef = useRef<CustomerFilterFormRef>(null); | |
| - const debouncedOnCampaignUpdate = useDebouncedCallback(onCampaignUpdate, { | |
| - wait: 1000, | |
| - }); | |
| + const debouncedOnCampaignUpdate = useDebouncedCallback( | |
| + onCampaignUpdate, | |
| + 1000, | |
| + ); | |
| // Use custom hook for participant management | |
| const { | |
| @@ -73,13 +73,14 @@ export const CampaignParticipantsTab: React.FC< | |
| const updateCampaignMutation = useUpdateCampaign(); | |
| // Use shared filter management hook | |
| - const { handleFormSubmit } = useCampaignFilterManagement({ | |
| - campaignId: campaign?.id, | |
| - onFilterSaved: () => { | |
| - setIsEditingFilter(false); | |
| - }, | |
| - onCampaignUpdate, | |
| - }); | |
| + const { handleFilterSave, handleFormSubmit, isUpdatingCampaign } = | |
| + useCampaignFilterManagement({ | |
| + campaignId: campaign?.id, | |
| + onFilterSaved: () => { | |
| + setIsEditingFilter(false); | |
| + }, | |
| + onCampaignUpdate, | |
| + }); | |
| // Determine current selection mode based on campaign state | |
| const getCurrentMode = useCallback((): SelectionMode => { | |
| diff --git a/src/pages/marketing/components/conditions/ConditionFormDialog.tsx b/src/pages/marketing/components/conditions/ConditionFormDialog.tsx | |
| index 511788a3..b04c048e 100644 | |
| --- a/src/pages/marketing/components/conditions/ConditionFormDialog.tsx | |
| +++ b/src/pages/marketing/components/conditions/ConditionFormDialog.tsx | |
| @@ -60,9 +60,7 @@ export const ConditionFormDialog: React.FC<ConditionDialogProps> = ({ | |
| }, | |
| }); | |
| - const { reset, handleSubmit, trigger } = form; | |
| - | |
| - console.log(form.formState.errors); | |
| + const { reset, handleSubmit } = form; | |
| // Reset form when dialog opens/closes or initial condition changes | |
| useEffect(() => { | |
| @@ -71,8 +69,6 @@ export const ConditionFormDialog: React.FC<ConditionDialogProps> = ({ | |
| // Transform existing condition to form format | |
| const formData = transformFromCondition(initialCondition); | |
| reset(formData as ConditionFormData); | |
| - // Trigger validation after reset to ensure form state is updated | |
| - void trigger(); | |
| } else { | |
| // Set defaults for new condition | |
| const type = allowedTypes[0]; | |
| @@ -133,7 +129,7 @@ export const ConditionFormDialog: React.FC<ConditionDialogProps> = ({ | |
| }); | |
| } | |
| } | |
| - }, [open, initialCondition, allowedTypes, reset, trigger]); | |
| + }, [open, initialCondition, allowedTypes, reset]); | |
| const onSubmit = async (data: ConditionFormData) => { | |
| try { | |
| diff --git a/src/pages/paymentProcessor/PaymentProcessorReportsPage.tsx b/src/pages/paymentProcessor/PaymentProcessorReportsPage.tsx | |
| index 40c4dd6c..3b10c93f 100644 | |
| --- a/src/pages/paymentProcessor/PaymentProcessorReportsPage.tsx | |
| +++ b/src/pages/paymentProcessor/PaymentProcessorReportsPage.tsx | |
| @@ -13,7 +13,7 @@ const PaymentProcessorReportsPage = () => { | |
| const { value: feeReportEnabled } = useEntityConfig( | |
| EntityConfigKey.FEE_REPORT, | |
| - true, | |
| + false, | |
| entity.id, | |
| ); | |
| diff --git a/src/pages/report/SalesByTimeReport.tsx b/src/pages/report/SalesByTimeReport.tsx | |
| index d0400eed..3ed4d00f 100644 | |
| --- a/src/pages/report/SalesByTimeReport.tsx | |
| +++ b/src/pages/report/SalesByTimeReport.tsx | |
| @@ -179,7 +179,6 @@ const SalesByTimeReport: React.FC<SalesByTimeReportProps> = ({ | |
| to: end, | |
| }); | |
| } | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [start, end]); | |
| const { data, isFetching } = useGetSalesByTimeIntervalChanged({ | |
| diff --git a/src/pages/report/TotalsReport/TotalsReportPage.tsx b/src/pages/report/TotalsReport/TotalsReportPage.tsx | |
| index e2d55cce..45f13c5d 100644 | |
| --- a/src/pages/report/TotalsReport/TotalsReportPage.tsx | |
| +++ b/src/pages/report/TotalsReport/TotalsReportPage.tsx | |
| @@ -200,7 +200,6 @@ const TotalsReportPage = () => { | |
| useEffect(() => { | |
| void onSearch(); | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [entitySelectedId]); | |
| // Reset hasSearched when search params change (but not for preset clicks) | |
| diff --git a/src/pages/shelftalker/tasks/CreateShelfTalkerTaskDialog.tsx b/src/pages/shelftalker/tasks/CreateShelfTalkerTaskDialog.tsx | |
| index 646eaee0..aa02156e 100644 | |
| --- a/src/pages/shelftalker/tasks/CreateShelfTalkerTaskDialog.tsx | |
| +++ b/src/pages/shelftalker/tasks/CreateShelfTalkerTaskDialog.tsx | |
| @@ -82,7 +82,6 @@ export function CreateShelfTalkerTaskDialog({ | |
| setStep("completed"); | |
| await onTaskComplete?.(); | |
| }, | |
| - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| [toast, queryClient], | |
| ); | |
| diff --git a/src/phoenix-generated/clients/createWebsocketConnection.ts b/src/phoenix-generated/clients/createWebsocketConnection.ts | |
| deleted file mode 100644 | |
| index 1b034468..00000000 | |
| --- a/src/phoenix-generated/clients/createWebsocketConnection.ts | |
| +++ /dev/null | |
| @@ -1,22 +0,0 @@ | |
| -import type { ResponseConfig } from "../../config/phoenix-client"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - CreateWebsocketConnectionMutationRequest, | |
| - CreateWebsocketConnectionMutationResponse, | |
| -} from "../types/CreateWebsocketConnection"; | |
| - | |
| -/** | |
| - * @description Create a websocket connection | |
| - * @summary Create a websocket connection | |
| - * @link /websocket/connection | |
| - */ | |
| -export async function createWebsocketConnection( | |
| - data: CreateWebsocketConnectionMutationRequest, | |
| - options: Partial<Parameters<typeof client>[0]> = {}, | |
| -): Promise<ResponseConfig<CreateWebsocketConnectionMutationResponse>["data"]> { | |
| - const res = await client< | |
| - CreateWebsocketConnectionMutationResponse, | |
| - CreateWebsocketConnectionMutationRequest | |
| - >({ method: "post", url: `/websocket/connection`, data, ...options }); | |
| - return res.data; | |
| -} | |
| diff --git a/src/phoenix-generated/clients/getTransactionByTransactionItem.ts b/src/phoenix-generated/clients/getTransactionByTransactionItem.ts | |
| deleted file mode 100644 | |
| index 72752598..00000000 | |
| --- a/src/phoenix-generated/clients/getTransactionByTransactionItem.ts | |
| +++ /dev/null | |
| @@ -1,25 +0,0 @@ | |
| -import type { ResponseConfig } from "../../config/phoenix-client"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetTransactionByTransactionItemPathParams, | |
| - GetTransactionByTransactionItemQueryResponse, | |
| -} from "../types/GetTransactionByTransactionItem"; | |
| - | |
| -/** | |
| - * @description Get transaction by transaction item ID | |
| - * @summary Get transaction by transaction item | |
| - * @link /transaction/transaction-item/:id | |
| - */ | |
| -export async function getTransactionByTransactionItem( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| - options: Partial<Parameters<typeof client>[0]> = {}, | |
| -): Promise< | |
| - ResponseConfig<GetTransactionByTransactionItemQueryResponse>["data"] | |
| -> { | |
| - const res = await client<GetTransactionByTransactionItemQueryResponse>({ | |
| - method: "get", | |
| - url: `/transaction/transaction-item/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| -} | |
| diff --git a/src/phoenix-generated/clients/index.ts b/src/phoenix-generated/clients/index.ts | |
| deleted file mode 100644 | |
| index bf4fa97d..00000000 | |
| --- a/src/phoenix-generated/clients/index.ts | |
| +++ /dev/null | |
| @@ -1,4 +0,0 @@ | |
| -export * from "./createWebsocketConnection"; | |
| -export * from "./getTransactionByTransactionItem"; | |
| -export * from "./removeWebsocketConnection"; | |
| -export * from "./updateOrderItemDecisionStatus"; | |
| diff --git a/src/phoenix-generated/clients/operations.ts b/src/phoenix-generated/clients/operations.ts | |
| deleted file mode 100644 | |
| index 1f18c76e..00000000 | |
| --- a/src/phoenix-generated/clients/operations.ts | |
| +++ /dev/null | |
| @@ -1,18 +0,0 @@ | |
| -export const operations = { | |
| - updateOrderItemDecisionStatus: { | |
| - path: "/order-item-decisions/:id/status", | |
| - method: "put", | |
| - }, | |
| - getTransactionByTransactionItem: { | |
| - path: "/transaction/transaction-item/:id", | |
| - method: "get", | |
| - }, | |
| - createWebsocketConnection: { | |
| - path: "/websocket/connection", | |
| - method: "post", | |
| - }, | |
| - removeWebsocketConnection: { | |
| - path: "/websocket/connection/:connectionID", | |
| - method: "delete", | |
| - }, | |
| -} as const; | |
| diff --git a/src/phoenix-generated/clients/removeWebsocketConnection.ts b/src/phoenix-generated/clients/removeWebsocketConnection.ts | |
| deleted file mode 100644 | |
| index 7175eca9..00000000 | |
| --- a/src/phoenix-generated/clients/removeWebsocketConnection.ts | |
| +++ /dev/null | |
| @@ -1,23 +0,0 @@ | |
| -import type { ResponseConfig } from "../../config/phoenix-client"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - RemoveWebsocketConnectionMutationResponse, | |
| - RemoveWebsocketConnectionPathParams, | |
| -} from "../types/RemoveWebsocketConnection"; | |
| - | |
| -/** | |
| - * @description Delete a websocket connection | |
| - * @summary Delete a websocket connection | |
| - * @link /websocket/connection/:connectionID | |
| - */ | |
| -export async function removeWebsocketConnection( | |
| - connectionId: RemoveWebsocketConnectionPathParams["connectionID"], | |
| - options: Partial<Parameters<typeof client>[0]> = {}, | |
| -): Promise<ResponseConfig<RemoveWebsocketConnectionMutationResponse>["data"]> { | |
| - const res = await client<RemoveWebsocketConnectionMutationResponse>({ | |
| - method: "delete", | |
| - url: `/websocket/connection/${connectionId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| -} | |
| diff --git a/src/phoenix-generated/clients/updateOrderItemDecisionStatus.ts b/src/phoenix-generated/clients/updateOrderItemDecisionStatus.ts | |
| deleted file mode 100644 | |
| index 943af6c5..00000000 | |
| --- a/src/phoenix-generated/clients/updateOrderItemDecisionStatus.ts | |
| +++ /dev/null | |
| @@ -1,31 +0,0 @@ | |
| -import type { ResponseConfig } from "../../config/phoenix-client"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - UpdateOrderItemDecisionStatusMutationRequest, | |
| - UpdateOrderItemDecisionStatusMutationResponse, | |
| - UpdateOrderItemDecisionStatusPathParams, | |
| -} from "../types/UpdateOrderItemDecisionStatus"; | |
| - | |
| -/** | |
| - * @description Update the status of an order item decision | |
| - * @summary Update order item decision status | |
| - * @link /order-item-decisions/:id/status | |
| - */ | |
| -export async function updateOrderItemDecisionStatus( | |
| - id: UpdateOrderItemDecisionStatusPathParams["id"], | |
| - data: UpdateOrderItemDecisionStatusMutationRequest, | |
| - options: Partial<Parameters<typeof client>[0]> = {}, | |
| -): Promise< | |
| - ResponseConfig<UpdateOrderItemDecisionStatusMutationResponse>["data"] | |
| -> { | |
| - const res = await client< | |
| - UpdateOrderItemDecisionStatusMutationResponse, | |
| - UpdateOrderItemDecisionStatusMutationRequest | |
| - >({ | |
| - method: "put", | |
| - url: `/order-item-decisions/${id}/status`, | |
| - data, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/index.ts b/src/phoenix-generated/hooks/index.ts | |
| deleted file mode 100644 | |
| index e60f5e3d..00000000 | |
| --- a/src/phoenix-generated/hooks/index.ts | |
| +++ /dev/null | |
| @@ -1,55 +0,0 @@ | |
| -export * from "./useCreateLoyaltyCustomerMessage"; | |
| -export * from "./useCreateOrderItemDecision"; | |
| -export * from "./useCreateWebsocketConnection"; | |
| -export * from "./useDeleteFulfillmentId"; | |
| -export * from "./useDeleteOrderItemDecisionsId"; | |
| -export * from "./useDeleteStorefrontPagesPageid"; | |
| -export * from "./useDeleteStoreHoursEntitySalesChannelEntitySalesChannelId"; | |
| -export * from "./useGet"; | |
| -export * from "./useGetCategories"; | |
| -export * from "./useGetCategoriesHierarchy"; | |
| -export * from "./useGetCustomerId"; | |
| -export * from "./useGetEntityId"; | |
| -export * from "./useGetFulfillment"; | |
| -export * from "./useGetFulfillmentOrderItemOrderItemId"; | |
| -export * from "./useGetHealth"; | |
| -export * from "./useGetLoyaltyCustomer"; | |
| -export * from "./useGetLoyaltyCustomerIdPoints"; | |
| -export * from "./useGetOrderItemDecision"; | |
| -export * from "./useGetOrderItemDecisionsTransactionItemTransactionItemId"; | |
| -export * from "./useGetProducts"; | |
| -export * from "./useGetProductsProductId"; | |
| -export * from "./useGetProductsStorefrontStorefrontIdPathPath"; | |
| -export * from "./useGetStorefrontPagesPageid"; | |
| -export * from "./useGetStorefrontsCustomDomainCustomDomain"; | |
| -export * from "./useGetStorefrontsId"; | |
| -export * from "./useGetStorefrontsIdPages"; | |
| -export * from "./useGetStorefrontsSubdomainSubdomain"; | |
| -export * from "./useGetStorefrontsSubdomainSubdomainCheck"; | |
| -export * from "./useGetStorefrontsSubdomainSubdomainPagesPath"; | |
| -export * from "./useGetStoreHoursEntitySalesChannelEntitySalesChannelId"; | |
| -export * from "./useGetTransactionByTransactionItem"; | |
| -export * from "./useGetTransactionId"; | |
| -export * from "./useGetTransactionItemId"; | |
| -export * from "./useGetWebsocketConnections"; | |
| -export * from "./useGetWebsocketMessage"; | |
| -export * from "./useListFulfillments"; | |
| -export * from "./useListLoyaltyCustomers"; | |
| -export * from "./useListOrderItemDecisions"; | |
| -export * from "./useListStorefronts"; | |
| -export * from "./useListTransactionItems"; | |
| -export * from "./useListTransactions"; | |
| -export * from "./usePatchFulfillmentId"; | |
| -export * from "./usePatchStorefrontsId"; | |
| -export * from "./usePostCustomer"; | |
| -export * from "./usePostFulfillment"; | |
| -export * from "./usePostLoyaltyCustomer"; | |
| -export * from "./usePostStorefronts"; | |
| -export * from "./usePostStorefrontsIdAssetsPresignedUrl"; | |
| -export * from "./usePostStorefrontsIdPages"; | |
| -export * from "./usePostStoreHoursEntitySalesChannelEntitySalesChannelId"; | |
| -export * from "./usePutCustomer"; | |
| -export * from "./usePutStorefrontPagesPageid"; | |
| -export * from "./usePutStoreHoursEntitySalesChannelEntitySalesChannelId"; | |
| -export * from "./useRemoveWebsocketConnection"; | |
| -export * from "./useUpdateOrderItemDecisionStatus"; | |
| diff --git a/src/phoenix-generated/hooks/useCreateLoyaltyCustomerMessage.ts b/src/phoenix-generated/hooks/useCreateLoyaltyCustomerMessage.ts | |
| deleted file mode 100644 | |
| index 173f678a..00000000 | |
| --- a/src/phoenix-generated/hooks/useCreateLoyaltyCustomerMessage.ts | |
| +++ /dev/null | |
| @@ -1,73 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - CreateLoyaltyCustomerMessage400, | |
| - CreateLoyaltyCustomerMessage401, | |
| - CreateLoyaltyCustomerMessage422, | |
| - CreateLoyaltyCustomerMessage500, | |
| - CreateLoyaltyCustomerMessageMutationRequest, | |
| - CreateLoyaltyCustomerMessageMutationResponse, | |
| -} from "../types/CreateLoyaltyCustomerMessage"; | |
| - | |
| -type CreateLoyaltyCustomerMessageClient = typeof client< | |
| - CreateLoyaltyCustomerMessageMutationResponse, | |
| - | CreateLoyaltyCustomerMessage400 | |
| - | CreateLoyaltyCustomerMessage401 | |
| - | CreateLoyaltyCustomerMessage422 | |
| - | CreateLoyaltyCustomerMessage500, | |
| - CreateLoyaltyCustomerMessageMutationRequest | |
| ->; | |
| -type CreateLoyaltyCustomerMessage = { | |
| - data: CreateLoyaltyCustomerMessageMutationResponse; | |
| - error: | |
| - | CreateLoyaltyCustomerMessage400 | |
| - | CreateLoyaltyCustomerMessage401 | |
| - | CreateLoyaltyCustomerMessage422 | |
| - | CreateLoyaltyCustomerMessage500; | |
| - request: CreateLoyaltyCustomerMessageMutationRequest; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: CreateLoyaltyCustomerMessageMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<CreateLoyaltyCustomerMessageClient>[0]>; | |
| - return: Awaited<ReturnType<CreateLoyaltyCustomerMessageClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Create a new loyalty customer message | |
| - * @summary Create loyalty customer message | |
| - * @link /loyalty-customer/message | |
| - */ | |
| -export function useCreateLoyaltyCustomerMessage( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - CreateLoyaltyCustomerMessage["response"], | |
| - CreateLoyaltyCustomerMessage["error"], | |
| - { | |
| - data: CreateLoyaltyCustomerMessage["request"]; | |
| - } | |
| - >; | |
| - client?: CreateLoyaltyCustomerMessage["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ data }) => { | |
| - const res = await client< | |
| - CreateLoyaltyCustomerMessage["data"], | |
| - CreateLoyaltyCustomerMessage["error"], | |
| - CreateLoyaltyCustomerMessage["request"] | |
| - >({ | |
| - method: "post", | |
| - url: `/loyalty-customer/message`, | |
| - data, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useCreateOrderItemDecision.ts b/src/phoenix-generated/hooks/useCreateOrderItemDecision.ts | |
| deleted file mode 100644 | |
| index e3087bbd..00000000 | |
| --- a/src/phoenix-generated/hooks/useCreateOrderItemDecision.ts | |
| +++ /dev/null | |
| @@ -1,73 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - CreateOrderItemDecision400, | |
| - CreateOrderItemDecision401, | |
| - CreateOrderItemDecision422, | |
| - CreateOrderItemDecision500, | |
| - CreateOrderItemDecisionMutationRequest, | |
| - CreateOrderItemDecisionMutationResponse, | |
| -} from "../types/CreateOrderItemDecision"; | |
| - | |
| -type CreateOrderItemDecisionClient = typeof client< | |
| - CreateOrderItemDecisionMutationResponse, | |
| - | CreateOrderItemDecision400 | |
| - | CreateOrderItemDecision401 | |
| - | CreateOrderItemDecision422 | |
| - | CreateOrderItemDecision500, | |
| - CreateOrderItemDecisionMutationRequest | |
| ->; | |
| -type CreateOrderItemDecision = { | |
| - data: CreateOrderItemDecisionMutationResponse; | |
| - error: | |
| - | CreateOrderItemDecision400 | |
| - | CreateOrderItemDecision401 | |
| - | CreateOrderItemDecision422 | |
| - | CreateOrderItemDecision500; | |
| - request: CreateOrderItemDecisionMutationRequest; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: CreateOrderItemDecisionMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<CreateOrderItemDecisionClient>[0]>; | |
| - return: Awaited<ReturnType<CreateOrderItemDecisionClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Create a new order item decision | |
| - * @summary Create order item decision | |
| - * @link /order-item-decisions | |
| - */ | |
| -export function useCreateOrderItemDecision( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - CreateOrderItemDecision["response"], | |
| - CreateOrderItemDecision["error"], | |
| - { | |
| - data: CreateOrderItemDecision["request"]; | |
| - } | |
| - >; | |
| - client?: CreateOrderItemDecision["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ data }) => { | |
| - const res = await client< | |
| - CreateOrderItemDecision["data"], | |
| - CreateOrderItemDecision["error"], | |
| - CreateOrderItemDecision["request"] | |
| - >({ | |
| - method: "post", | |
| - url: `/order-item-decisions`, | |
| - data, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useCreateWebsocketConnection.ts b/src/phoenix-generated/hooks/useCreateWebsocketConnection.ts | |
| deleted file mode 100644 | |
| index 72c086e2..00000000 | |
| --- a/src/phoenix-generated/hooks/useCreateWebsocketConnection.ts | |
| +++ /dev/null | |
| @@ -1,70 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - CreateWebsocketConnection400, | |
| - CreateWebsocketConnection401, | |
| - CreateWebsocketConnection500, | |
| - CreateWebsocketConnectionMutationRequest, | |
| - CreateWebsocketConnectionMutationResponse, | |
| -} from "../types/CreateWebsocketConnection"; | |
| - | |
| -type CreateWebsocketConnectionClient = typeof client< | |
| - CreateWebsocketConnectionMutationResponse, | |
| - | CreateWebsocketConnection400 | |
| - | CreateWebsocketConnection401 | |
| - | CreateWebsocketConnection500, | |
| - CreateWebsocketConnectionMutationRequest | |
| ->; | |
| -type CreateWebsocketConnection = { | |
| - data: CreateWebsocketConnectionMutationResponse; | |
| - error: | |
| - | CreateWebsocketConnection400 | |
| - | CreateWebsocketConnection401 | |
| - | CreateWebsocketConnection500; | |
| - request: CreateWebsocketConnectionMutationRequest; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: CreateWebsocketConnectionMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<CreateWebsocketConnectionClient>[0]>; | |
| - return: Awaited<ReturnType<CreateWebsocketConnectionClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Create a websocket connection | |
| - * @summary Create a websocket connection | |
| - * @link /websocket/connection | |
| - */ | |
| -export function useCreateWebsocketConnection( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - CreateWebsocketConnection["response"], | |
| - CreateWebsocketConnection["error"], | |
| - { | |
| - data: CreateWebsocketConnection["request"]; | |
| - } | |
| - >; | |
| - client?: CreateWebsocketConnection["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ data }) => { | |
| - const res = await client< | |
| - CreateWebsocketConnection["data"], | |
| - CreateWebsocketConnection["error"], | |
| - CreateWebsocketConnection["request"] | |
| - >({ | |
| - method: "post", | |
| - url: `/websocket/connection`, | |
| - data, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useDeleteFulfillmentId.ts b/src/phoenix-generated/hooks/useDeleteFulfillmentId.ts | |
| deleted file mode 100644 | |
| index d5ef28f4..00000000 | |
| --- a/src/phoenix-generated/hooks/useDeleteFulfillmentId.ts | |
| +++ /dev/null | |
| @@ -1,72 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - DeleteFulfillmentId400, | |
| - DeleteFulfillmentId401, | |
| - DeleteFulfillmentId404, | |
| - DeleteFulfillmentId500, | |
| - DeleteFulfillmentIdMutationResponse, | |
| - DeleteFulfillmentIdPathParams, | |
| -} from "../types/DeleteFulfillmentId"; | |
| - | |
| -type DeleteFulfillmentIdClient = typeof client< | |
| - DeleteFulfillmentIdMutationResponse, | |
| - | DeleteFulfillmentId400 | |
| - | DeleteFulfillmentId401 | |
| - | DeleteFulfillmentId404 | |
| - | DeleteFulfillmentId500, | |
| - never | |
| ->; | |
| -type DeleteFulfillmentId = { | |
| - data: DeleteFulfillmentIdMutationResponse; | |
| - error: | |
| - | DeleteFulfillmentId400 | |
| - | DeleteFulfillmentId401 | |
| - | DeleteFulfillmentId404 | |
| - | DeleteFulfillmentId500; | |
| - request: never; | |
| - pathParams: DeleteFulfillmentIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: DeleteFulfillmentIdMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<DeleteFulfillmentIdClient>[0]>; | |
| - return: Awaited<ReturnType<DeleteFulfillmentIdClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Delete a fulfillment by ID | |
| - * @summary Delete fulfillment | |
| - * @link /fulfillment/:id | |
| - */ | |
| -export function useDeleteFulfillmentId( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - DeleteFulfillmentId["response"], | |
| - DeleteFulfillmentId["error"], | |
| - { | |
| - id: DeleteFulfillmentIdPathParams["id"]; | |
| - } | |
| - >; | |
| - client?: DeleteFulfillmentId["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ id }) => { | |
| - const res = await client< | |
| - DeleteFulfillmentId["data"], | |
| - DeleteFulfillmentId["error"], | |
| - DeleteFulfillmentId["request"] | |
| - >({ | |
| - method: "delete", | |
| - url: `/fulfillment/${id}`, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useDeleteOrderItemDecisionsId.ts b/src/phoenix-generated/hooks/useDeleteOrderItemDecisionsId.ts | |
| deleted file mode 100644 | |
| index e91a46ed..00000000 | |
| --- a/src/phoenix-generated/hooks/useDeleteOrderItemDecisionsId.ts | |
| +++ /dev/null | |
| @@ -1,72 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - DeleteOrderItemDecisionsId400, | |
| - DeleteOrderItemDecisionsId401, | |
| - DeleteOrderItemDecisionsId404, | |
| - DeleteOrderItemDecisionsId500, | |
| - DeleteOrderItemDecisionsIdMutationResponse, | |
| - DeleteOrderItemDecisionsIdPathParams, | |
| -} from "../types/DeleteOrderItemDecisionsId"; | |
| - | |
| -type DeleteOrderItemDecisionsIdClient = typeof client< | |
| - DeleteOrderItemDecisionsIdMutationResponse, | |
| - | DeleteOrderItemDecisionsId400 | |
| - | DeleteOrderItemDecisionsId401 | |
| - | DeleteOrderItemDecisionsId404 | |
| - | DeleteOrderItemDecisionsId500, | |
| - never | |
| ->; | |
| -type DeleteOrderItemDecisionsId = { | |
| - data: DeleteOrderItemDecisionsIdMutationResponse; | |
| - error: | |
| - | DeleteOrderItemDecisionsId400 | |
| - | DeleteOrderItemDecisionsId401 | |
| - | DeleteOrderItemDecisionsId404 | |
| - | DeleteOrderItemDecisionsId500; | |
| - request: never; | |
| - pathParams: DeleteOrderItemDecisionsIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: DeleteOrderItemDecisionsIdMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<DeleteOrderItemDecisionsIdClient>[0]>; | |
| - return: Awaited<ReturnType<DeleteOrderItemDecisionsIdClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Delete an order item decision | |
| - * @summary Delete order item decision | |
| - * @link /order-item-decisions/:id | |
| - */ | |
| -export function useDeleteOrderItemDecisionsId( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - DeleteOrderItemDecisionsId["response"], | |
| - DeleteOrderItemDecisionsId["error"], | |
| - { | |
| - id: DeleteOrderItemDecisionsIdPathParams["id"]; | |
| - } | |
| - >; | |
| - client?: DeleteOrderItemDecisionsId["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ id }) => { | |
| - const res = await client< | |
| - DeleteOrderItemDecisionsId["data"], | |
| - DeleteOrderItemDecisionsId["error"], | |
| - DeleteOrderItemDecisionsId["request"] | |
| - >({ | |
| - method: "delete", | |
| - url: `/order-item-decisions/${id}`, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useDeleteStoreHoursEntitySalesChannelEntitySalesChannelId.ts b/src/phoenix-generated/hooks/useDeleteStoreHoursEntitySalesChannelEntitySalesChannelId.ts | |
| deleted file mode 100644 | |
| index ee5d160c..00000000 | |
| --- a/src/phoenix-generated/hooks/useDeleteStoreHoursEntitySalesChannelEntitySalesChannelId.ts | |
| +++ /dev/null | |
| @@ -1,71 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId400, | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId500, | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdMutationResponse, | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams, | |
| -} from "../types/DeleteStoreHoursEntitySalesChannelEntitySalesChannelId"; | |
| - | |
| -type DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdClient = | |
| - typeof client< | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdMutationResponse, | |
| - | DeleteStoreHoursEntitySalesChannelEntitySalesChannelId400 | |
| - | DeleteStoreHoursEntitySalesChannelEntitySalesChannelId500, | |
| - never | |
| - >; | |
| -type DeleteStoreHoursEntitySalesChannelEntitySalesChannelId = { | |
| - data: DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdMutationResponse; | |
| - error: | |
| - | DeleteStoreHoursEntitySalesChannelEntitySalesChannelId400 | |
| - | DeleteStoreHoursEntitySalesChannelEntitySalesChannelId500; | |
| - request: never; | |
| - pathParams: DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdMutationResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdClient>[0] | |
| - >; | |
| - return: Awaited< | |
| - ReturnType<DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdClient> | |
| - >; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Delete all store hours for an entity sales channel | |
| - * @summary Delete store hours for entity sales channel | |
| - * @link /store-hours/entity-sales-channel/:entity_sales_channel_id | |
| - */ | |
| -export function useDeleteStoreHoursEntitySalesChannelEntitySalesChannelId( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId["response"], | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId["error"], | |
| - { | |
| - entitySalesChannelId: DeleteStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"]; | |
| - } | |
| - >; | |
| - client?: DeleteStoreHoursEntitySalesChannelEntitySalesChannelId["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ entitySalesChannelId }) => { | |
| - const res = await client< | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId["data"], | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId["error"], | |
| - DeleteStoreHoursEntitySalesChannelEntitySalesChannelId["request"] | |
| - >({ | |
| - method: "delete", | |
| - url: `/store-hours/entity-sales-channel/${entitySalesChannelId}`, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useDeleteStorefrontPagesPageid.ts b/src/phoenix-generated/hooks/useDeleteStorefrontPagesPageid.ts | |
| deleted file mode 100644 | |
| index dc45871c..00000000 | |
| --- a/src/phoenix-generated/hooks/useDeleteStorefrontPagesPageid.ts | |
| +++ /dev/null | |
| @@ -1,72 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - DeleteStorefrontPagesPageid400, | |
| - DeleteStorefrontPagesPageid401, | |
| - DeleteStorefrontPagesPageid404, | |
| - DeleteStorefrontPagesPageid500, | |
| - DeleteStorefrontPagesPageidMutationResponse, | |
| - DeleteStorefrontPagesPageidPathParams, | |
| -} from "../types/DeleteStorefrontPagesPageid"; | |
| - | |
| -type DeleteStorefrontPagesPageidClient = typeof client< | |
| - DeleteStorefrontPagesPageidMutationResponse, | |
| - | DeleteStorefrontPagesPageid400 | |
| - | DeleteStorefrontPagesPageid401 | |
| - | DeleteStorefrontPagesPageid404 | |
| - | DeleteStorefrontPagesPageid500, | |
| - never | |
| ->; | |
| -type DeleteStorefrontPagesPageid = { | |
| - data: DeleteStorefrontPagesPageidMutationResponse; | |
| - error: | |
| - | DeleteStorefrontPagesPageid400 | |
| - | DeleteStorefrontPagesPageid401 | |
| - | DeleteStorefrontPagesPageid404 | |
| - | DeleteStorefrontPagesPageid500; | |
| - request: never; | |
| - pathParams: DeleteStorefrontPagesPageidPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: DeleteStorefrontPagesPageidMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<DeleteStorefrontPagesPageidClient>[0]>; | |
| - return: Awaited<ReturnType<DeleteStorefrontPagesPageidClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Delete a storefront page by its ID | |
| - * @summary Delete storefront page | |
| - * @link /storefront-pages/:pageId | |
| - */ | |
| -export function useDeleteStorefrontPagesPageid( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - DeleteStorefrontPagesPageid["response"], | |
| - DeleteStorefrontPagesPageid["error"], | |
| - { | |
| - pageId: DeleteStorefrontPagesPageidPathParams["pageId"]; | |
| - } | |
| - >; | |
| - client?: DeleteStorefrontPagesPageid["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ pageId }) => { | |
| - const res = await client< | |
| - DeleteStorefrontPagesPageid["data"], | |
| - DeleteStorefrontPagesPageid["error"], | |
| - DeleteStorefrontPagesPageid["request"] | |
| - >({ | |
| - method: "delete", | |
| - url: `/storefront-pages/${pageId}`, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGet.ts b/src/phoenix-generated/hooks/useGet.ts | |
| deleted file mode 100644 | |
| index 4dc61234..00000000 | |
| --- a/src/phoenix-generated/hooks/useGet.ts | |
| +++ /dev/null | |
| @@ -1,132 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { GetQueryResponse } from "../types/Get"; | |
| - | |
| -type GetClient = typeof client<GetQueryResponse, Error, never>; | |
| -type Get = { | |
| - data: GetQueryResponse; | |
| - error: Error; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetClient>[0]>; | |
| - return: Awaited<ReturnType<GetClient>>; | |
| - }; | |
| -}; | |
| -export const getQueryKey = () => [{ url: "/" }] as const; | |
| -export type GetQueryKey = ReturnType<typeof getQueryKey>; | |
| -export function getQueryOptions(options: Get["client"]["parameters"] = {}) { | |
| - const queryKey = getQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<Get["data"], Get["error"]>({ | |
| - method: "get", | |
| - url: `/`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Returns a welcome message | |
| - * @summary Get welcome message | |
| - * @link / | |
| - */ | |
| -export function useGet< | |
| - TData = Get["response"], | |
| - TQueryData = Get["response"], | |
| - TQueryKey extends QueryKey = GetQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - Get["response"], | |
| - Get["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: Get["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, Get["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getQueryKey(); | |
| - const query = useQuery({ | |
| - ...(getQueryOptions(clientOptions) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, Get["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getSuspenseQueryKey = () => [{ url: "/" }] as const; | |
| -export type GetSuspenseQueryKey = ReturnType<typeof getSuspenseQueryKey>; | |
| -export function getSuspenseQueryOptions( | |
| - options: Get["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getSuspenseQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<Get["data"], Get["error"]>({ | |
| - method: "get", | |
| - url: `/`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Returns a welcome message | |
| - * @summary Get welcome message | |
| - * @link / | |
| - */ | |
| -export function useGetSuspense< | |
| - TData = Get["response"], | |
| - TQueryKey extends QueryKey = GetSuspenseQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions<Get["response"], Get["error"], TData, TQueryKey> | |
| - >; | |
| - client?: Get["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, Get["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getSuspenseQueryKey(); | |
| - const query = useSuspenseQuery({ | |
| - ...(getSuspenseQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, Get["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetCategories.ts b/src/phoenix-generated/hooks/useGetCategories.ts | |
| deleted file mode 100644 | |
| index b5f6ef80..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetCategories.ts | |
| +++ /dev/null | |
| @@ -1,170 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetCategories400, | |
| - GetCategories401, | |
| - GetCategories422, | |
| - GetCategories500, | |
| - GetCategoriesQueryParams, | |
| - GetCategoriesQueryResponse, | |
| -} from "../types/GetCategories"; | |
| - | |
| -type GetCategoriesClient = typeof client< | |
| - GetCategoriesQueryResponse, | |
| - GetCategories400 | GetCategories401 | GetCategories422 | GetCategories500, | |
| - never | |
| ->; | |
| -type GetCategories = { | |
| - data: GetCategoriesQueryResponse; | |
| - error: | |
| - | GetCategories400 | |
| - | GetCategories401 | |
| - | GetCategories422 | |
| - | GetCategories500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: GetCategoriesQueryParams; | |
| - headerParams: never; | |
| - response: GetCategoriesQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetCategoriesClient>[0]>; | |
| - return: Awaited<ReturnType<GetCategoriesClient>>; | |
| - }; | |
| -}; | |
| -export const getCategoriesQueryKey = (params?: GetCategories["queryParams"]) => | |
| - [{ url: "/categories" }, ...(params ? [params] : [])] as const; | |
| -export type GetCategoriesQueryKey = ReturnType<typeof getCategoriesQueryKey>; | |
| -export function getCategoriesQueryOptions( | |
| - params?: GetCategories["queryParams"], | |
| - options: GetCategories["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getCategoriesQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetCategories["data"], GetCategories["error"]>({ | |
| - method: "get", | |
| - url: `/categories`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List categories with pagination and optional search | |
| - * @summary List categories | |
| - * @link /categories | |
| - */ | |
| -export function useGetCategories< | |
| - TData = GetCategories["response"], | |
| - TQueryData = GetCategories["response"], | |
| - TQueryKey extends QueryKey = GetCategoriesQueryKey, | |
| ->( | |
| - params?: GetCategories["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetCategories["response"], | |
| - GetCategories["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetCategories["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetCategories["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getCategoriesQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(getCategoriesQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetCategories["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getCategoriesSuspenseQueryKey = ( | |
| - params?: GetCategories["queryParams"], | |
| -) => [{ url: "/categories" }, ...(params ? [params] : [])] as const; | |
| -export type GetCategoriesSuspenseQueryKey = ReturnType< | |
| - typeof getCategoriesSuspenseQueryKey | |
| ->; | |
| -export function getCategoriesSuspenseQueryOptions( | |
| - params?: GetCategories["queryParams"], | |
| - options: GetCategories["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getCategoriesSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetCategories["data"], GetCategories["error"]>({ | |
| - method: "get", | |
| - url: `/categories`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List categories with pagination and optional search | |
| - * @summary List categories | |
| - * @link /categories | |
| - */ | |
| -export function useGetCategoriesSuspense< | |
| - TData = GetCategories["response"], | |
| - TQueryKey extends QueryKey = GetCategoriesSuspenseQueryKey, | |
| ->( | |
| - params?: GetCategories["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetCategories["response"], | |
| - GetCategories["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetCategories["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetCategories["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getCategoriesSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(getCategoriesSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetCategories["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetCategoriesHierarchy.ts b/src/phoenix-generated/hooks/useGetCategoriesHierarchy.ts | |
| deleted file mode 100644 | |
| index 9a03f42e..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetCategoriesHierarchy.ts | |
| +++ /dev/null | |
| @@ -1,161 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetCategoriesHierarchy500, | |
| - GetCategoriesHierarchyQueryResponse, | |
| -} from "../types/GetCategoriesHierarchy"; | |
| - | |
| -type GetCategoriesHierarchyClient = typeof client< | |
| - GetCategoriesHierarchyQueryResponse, | |
| - GetCategoriesHierarchy500, | |
| - never | |
| ->; | |
| -type GetCategoriesHierarchy = { | |
| - data: GetCategoriesHierarchyQueryResponse; | |
| - error: GetCategoriesHierarchy500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetCategoriesHierarchyQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetCategoriesHierarchyClient>[0]>; | |
| - return: Awaited<ReturnType<GetCategoriesHierarchyClient>>; | |
| - }; | |
| -}; | |
| -export const getCategoriesHierarchyQueryKey = () => | |
| - [{ url: "/categories/hierarchy" }] as const; | |
| -export type GetCategoriesHierarchyQueryKey = ReturnType< | |
| - typeof getCategoriesHierarchyQueryKey | |
| ->; | |
| -export function getCategoriesHierarchyQueryOptions( | |
| - options: GetCategoriesHierarchy["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getCategoriesHierarchyQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetCategoriesHierarchy["data"], | |
| - GetCategoriesHierarchy["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/categories/hierarchy`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get all categories in a hierarchical structure with nested children | |
| - * @summary Get categories hierarchy | |
| - * @link /categories/hierarchy | |
| - */ | |
| -export function useGetCategoriesHierarchy< | |
| - TData = GetCategoriesHierarchy["response"], | |
| - TQueryData = GetCategoriesHierarchy["response"], | |
| - TQueryKey extends QueryKey = GetCategoriesHierarchyQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetCategoriesHierarchy["response"], | |
| - GetCategoriesHierarchy["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetCategoriesHierarchy["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetCategoriesHierarchy["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getCategoriesHierarchyQueryKey(); | |
| - const query = useQuery({ | |
| - ...(getCategoriesHierarchyQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetCategoriesHierarchy["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getCategoriesHierarchySuspenseQueryKey = () => | |
| - [{ url: "/categories/hierarchy" }] as const; | |
| -export type GetCategoriesHierarchySuspenseQueryKey = ReturnType< | |
| - typeof getCategoriesHierarchySuspenseQueryKey | |
| ->; | |
| -export function getCategoriesHierarchySuspenseQueryOptions( | |
| - options: GetCategoriesHierarchy["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getCategoriesHierarchySuspenseQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetCategoriesHierarchy["data"], | |
| - GetCategoriesHierarchy["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/categories/hierarchy`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get all categories in a hierarchical structure with nested children | |
| - * @summary Get categories hierarchy | |
| - * @link /categories/hierarchy | |
| - */ | |
| -export function useGetCategoriesHierarchySuspense< | |
| - TData = GetCategoriesHierarchy["response"], | |
| - TQueryKey extends QueryKey = GetCategoriesHierarchySuspenseQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetCategoriesHierarchy["response"], | |
| - GetCategoriesHierarchy["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetCategoriesHierarchy["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetCategoriesHierarchy["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getCategoriesHierarchySuspenseQueryKey(); | |
| - const query = useSuspenseQuery({ | |
| - ...(getCategoriesHierarchySuspenseQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetCategoriesHierarchy["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetCustomerId.ts b/src/phoenix-generated/hooks/useGetCustomerId.ts | |
| deleted file mode 100644 | |
| index 0b3058d3..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetCustomerId.ts | |
| +++ /dev/null | |
| @@ -1,167 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetCustomerId400, | |
| - GetCustomerId401, | |
| - GetCustomerId404, | |
| - GetCustomerId500, | |
| - GetCustomerIdPathParams, | |
| - GetCustomerIdQueryResponse, | |
| -} from "../types/GetCustomerId"; | |
| - | |
| -type GetCustomerIdClient = typeof client< | |
| - GetCustomerIdQueryResponse, | |
| - GetCustomerId400 | GetCustomerId401 | GetCustomerId404 | GetCustomerId500, | |
| - never | |
| ->; | |
| -type GetCustomerId = { | |
| - data: GetCustomerIdQueryResponse; | |
| - error: | |
| - | GetCustomerId400 | |
| - | GetCustomerId401 | |
| - | GetCustomerId404 | |
| - | GetCustomerId500; | |
| - request: never; | |
| - pathParams: GetCustomerIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetCustomerIdQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetCustomerIdClient>[0]>; | |
| - return: Awaited<ReturnType<GetCustomerIdClient>>; | |
| - }; | |
| -}; | |
| -export const getCustomerIdQueryKey = (id: GetCustomerIdPathParams["id"]) => | |
| - [{ url: "/customer/:id", params: { id: id } }] as const; | |
| -export type GetCustomerIdQueryKey = ReturnType<typeof getCustomerIdQueryKey>; | |
| -export function getCustomerIdQueryOptions( | |
| - id: GetCustomerIdPathParams["id"], | |
| - options: GetCustomerId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getCustomerIdQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetCustomerId["data"], GetCustomerId["error"]>({ | |
| - method: "get", | |
| - url: `/customer/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a customer | |
| - * @summary Get customer | |
| - * @link /customer/:id | |
| - */ | |
| -export function useGetCustomerId< | |
| - TData = GetCustomerId["response"], | |
| - TQueryData = GetCustomerId["response"], | |
| - TQueryKey extends QueryKey = GetCustomerIdQueryKey, | |
| ->( | |
| - id: GetCustomerIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetCustomerId["response"], | |
| - GetCustomerId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetCustomerId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetCustomerId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getCustomerIdQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getCustomerIdQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetCustomerId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getCustomerIdSuspenseQueryKey = ( | |
| - id: GetCustomerIdPathParams["id"], | |
| -) => [{ url: "/customer/:id", params: { id: id } }] as const; | |
| -export type GetCustomerIdSuspenseQueryKey = ReturnType< | |
| - typeof getCustomerIdSuspenseQueryKey | |
| ->; | |
| -export function getCustomerIdSuspenseQueryOptions( | |
| - id: GetCustomerIdPathParams["id"], | |
| - options: GetCustomerId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getCustomerIdSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetCustomerId["data"], GetCustomerId["error"]>({ | |
| - method: "get", | |
| - url: `/customer/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a customer | |
| - * @summary Get customer | |
| - * @link /customer/:id | |
| - */ | |
| -export function useGetCustomerIdSuspense< | |
| - TData = GetCustomerId["response"], | |
| - TQueryKey extends QueryKey = GetCustomerIdSuspenseQueryKey, | |
| ->( | |
| - id: GetCustomerIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetCustomerId["response"], | |
| - GetCustomerId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetCustomerId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetCustomerId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getCustomerIdSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getCustomerIdSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetCustomerId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetEntityId.ts b/src/phoenix-generated/hooks/useGetEntityId.ts | |
| deleted file mode 100644 | |
| index 1a6e9d84..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetEntityId.ts | |
| +++ /dev/null | |
| @@ -1,162 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetEntityId400, | |
| - GetEntityId401, | |
| - GetEntityId404, | |
| - GetEntityId500, | |
| - GetEntityIdPathParams, | |
| - GetEntityIdQueryResponse, | |
| -} from "../types/GetEntityId"; | |
| - | |
| -type GetEntityIdClient = typeof client< | |
| - GetEntityIdQueryResponse, | |
| - GetEntityId400 | GetEntityId401 | GetEntityId404 | GetEntityId500, | |
| - never | |
| ->; | |
| -type GetEntityId = { | |
| - data: GetEntityIdQueryResponse; | |
| - error: GetEntityId400 | GetEntityId401 | GetEntityId404 | GetEntityId500; | |
| - request: never; | |
| - pathParams: GetEntityIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetEntityIdQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetEntityIdClient>[0]>; | |
| - return: Awaited<ReturnType<GetEntityIdClient>>; | |
| - }; | |
| -}; | |
| -export const getEntityIdQueryKey = (id: GetEntityIdPathParams["id"]) => | |
| - [{ url: "/entity/:id", params: { id: id } }] as const; | |
| -export type GetEntityIdQueryKey = ReturnType<typeof getEntityIdQueryKey>; | |
| -export function getEntityIdQueryOptions( | |
| - id: GetEntityIdPathParams["id"], | |
| - options: GetEntityId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getEntityIdQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetEntityId["data"], GetEntityId["error"]>({ | |
| - method: "get", | |
| - url: `/entity/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get entity by ID | |
| - * @summary Get entity | |
| - * @link /entity/:id | |
| - */ | |
| -export function useGetEntityId< | |
| - TData = GetEntityId["response"], | |
| - TQueryData = GetEntityId["response"], | |
| - TQueryKey extends QueryKey = GetEntityIdQueryKey, | |
| ->( | |
| - id: GetEntityIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetEntityId["response"], | |
| - GetEntityId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetEntityId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetEntityId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getEntityIdQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getEntityIdQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetEntityId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getEntityIdSuspenseQueryKey = (id: GetEntityIdPathParams["id"]) => | |
| - [{ url: "/entity/:id", params: { id: id } }] as const; | |
| -export type GetEntityIdSuspenseQueryKey = ReturnType< | |
| - typeof getEntityIdSuspenseQueryKey | |
| ->; | |
| -export function getEntityIdSuspenseQueryOptions( | |
| - id: GetEntityIdPathParams["id"], | |
| - options: GetEntityId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getEntityIdSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetEntityId["data"], GetEntityId["error"]>({ | |
| - method: "get", | |
| - url: `/entity/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get entity by ID | |
| - * @summary Get entity | |
| - * @link /entity/:id | |
| - */ | |
| -export function useGetEntityIdSuspense< | |
| - TData = GetEntityId["response"], | |
| - TQueryKey extends QueryKey = GetEntityIdSuspenseQueryKey, | |
| ->( | |
| - id: GetEntityIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetEntityId["response"], | |
| - GetEntityId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetEntityId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetEntityId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getEntityIdSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getEntityIdSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetEntityId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetFulfillment.ts b/src/phoenix-generated/hooks/useGetFulfillment.ts | |
| deleted file mode 100644 | |
| index 542b9605..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetFulfillment.ts | |
| +++ /dev/null | |
| @@ -1,171 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetFulfillment400, | |
| - GetFulfillment401, | |
| - GetFulfillment404, | |
| - GetFulfillment500, | |
| - GetFulfillmentPathParams, | |
| - GetFulfillmentQueryResponse, | |
| -} from "../types/GetFulfillment"; | |
| - | |
| -type GetFulfillmentClient = typeof client< | |
| - GetFulfillmentQueryResponse, | |
| - GetFulfillment400 | GetFulfillment401 | GetFulfillment404 | GetFulfillment500, | |
| - never | |
| ->; | |
| -type GetFulfillment = { | |
| - data: GetFulfillmentQueryResponse; | |
| - error: | |
| - | GetFulfillment400 | |
| - | GetFulfillment401 | |
| - | GetFulfillment404 | |
| - | GetFulfillment500; | |
| - request: never; | |
| - pathParams: GetFulfillmentPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetFulfillmentQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetFulfillmentClient>[0]>; | |
| - return: Awaited<ReturnType<GetFulfillmentClient>>; | |
| - }; | |
| -}; | |
| -export const getFulfillmentQueryKey = (id: GetFulfillmentPathParams["id"]) => | |
| - [{ url: "/fulfillment/:id", params: { id: id } }] as const; | |
| -export type GetFulfillmentQueryKey = ReturnType<typeof getFulfillmentQueryKey>; | |
| -export function getFulfillmentQueryOptions( | |
| - id: GetFulfillmentPathParams["id"], | |
| - options: GetFulfillment["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getFulfillmentQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetFulfillment["data"], GetFulfillment["error"]>( | |
| - { | |
| - method: "get", | |
| - url: `/fulfillment/${id}`, | |
| - ...options, | |
| - }, | |
| - ); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get fulfillment by ID | |
| - * @summary Get fulfillment | |
| - * @link /fulfillment/:id | |
| - */ | |
| -export function useGetFulfillment< | |
| - TData = GetFulfillment["response"], | |
| - TQueryData = GetFulfillment["response"], | |
| - TQueryKey extends QueryKey = GetFulfillmentQueryKey, | |
| ->( | |
| - id: GetFulfillmentPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetFulfillment["response"], | |
| - GetFulfillment["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetFulfillment["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetFulfillment["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getFulfillmentQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getFulfillmentQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetFulfillment["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getFulfillmentSuspenseQueryKey = ( | |
| - id: GetFulfillmentPathParams["id"], | |
| -) => [{ url: "/fulfillment/:id", params: { id: id } }] as const; | |
| -export type GetFulfillmentSuspenseQueryKey = ReturnType< | |
| - typeof getFulfillmentSuspenseQueryKey | |
| ->; | |
| -export function getFulfillmentSuspenseQueryOptions( | |
| - id: GetFulfillmentPathParams["id"], | |
| - options: GetFulfillment["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getFulfillmentSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetFulfillment["data"], GetFulfillment["error"]>( | |
| - { | |
| - method: "get", | |
| - url: `/fulfillment/${id}`, | |
| - ...options, | |
| - }, | |
| - ); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get fulfillment by ID | |
| - * @summary Get fulfillment | |
| - * @link /fulfillment/:id | |
| - */ | |
| -export function useGetFulfillmentSuspense< | |
| - TData = GetFulfillment["response"], | |
| - TQueryKey extends QueryKey = GetFulfillmentSuspenseQueryKey, | |
| ->( | |
| - id: GetFulfillmentPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetFulfillment["response"], | |
| - GetFulfillment["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetFulfillment["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetFulfillment["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getFulfillmentSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getFulfillmentSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetFulfillment["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetFulfillmentOrderItemOrderItemId.ts b/src/phoenix-generated/hooks/useGetFulfillmentOrderItemOrderItemId.ts | |
| deleted file mode 100644 | |
| index 78a36c67..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetFulfillmentOrderItemOrderItemId.ts | |
| +++ /dev/null | |
| @@ -1,205 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetFulfillmentOrderItemOrderItemId400, | |
| - GetFulfillmentOrderItemOrderItemId401, | |
| - GetFulfillmentOrderItemOrderItemId404, | |
| - GetFulfillmentOrderItemOrderItemId500, | |
| - GetFulfillmentOrderItemOrderItemIdPathParams, | |
| - GetFulfillmentOrderItemOrderItemIdQueryResponse, | |
| -} from "../types/GetFulfillmentOrderItemOrderItemId"; | |
| - | |
| -type GetFulfillmentOrderItemOrderItemIdClient = typeof client< | |
| - GetFulfillmentOrderItemOrderItemIdQueryResponse, | |
| - | GetFulfillmentOrderItemOrderItemId400 | |
| - | GetFulfillmentOrderItemOrderItemId401 | |
| - | GetFulfillmentOrderItemOrderItemId404 | |
| - | GetFulfillmentOrderItemOrderItemId500, | |
| - never | |
| ->; | |
| -type GetFulfillmentOrderItemOrderItemId = { | |
| - data: GetFulfillmentOrderItemOrderItemIdQueryResponse; | |
| - error: | |
| - | GetFulfillmentOrderItemOrderItemId400 | |
| - | GetFulfillmentOrderItemOrderItemId401 | |
| - | GetFulfillmentOrderItemOrderItemId404 | |
| - | GetFulfillmentOrderItemOrderItemId500; | |
| - request: never; | |
| - pathParams: GetFulfillmentOrderItemOrderItemIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetFulfillmentOrderItemOrderItemIdQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetFulfillmentOrderItemOrderItemIdClient>[0] | |
| - >; | |
| - return: Awaited<ReturnType<GetFulfillmentOrderItemOrderItemIdClient>>; | |
| - }; | |
| -}; | |
| -export const getFulfillmentOrderItemOrderItemIdQueryKey = ( | |
| - orderItemId: GetFulfillmentOrderItemOrderItemIdPathParams["order_item_id"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/fulfillment/order-item/:order_item_id", | |
| - params: { orderItemId: orderItemId }, | |
| - }, | |
| - ] as const; | |
| -export type GetFulfillmentOrderItemOrderItemIdQueryKey = ReturnType< | |
| - typeof getFulfillmentOrderItemOrderItemIdQueryKey | |
| ->; | |
| -export function getFulfillmentOrderItemOrderItemIdQueryOptions( | |
| - orderItemId: GetFulfillmentOrderItemOrderItemIdPathParams["order_item_id"], | |
| - options: GetFulfillmentOrderItemOrderItemId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getFulfillmentOrderItemOrderItemIdQueryKey(orderItemId); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetFulfillmentOrderItemOrderItemId["data"], | |
| - GetFulfillmentOrderItemOrderItemId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/fulfillment/order-item/${orderItemId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get fulfillment by order item ID | |
| - * @summary Get fulfillment by order item ID | |
| - * @link /fulfillment/order-item/:order_item_id | |
| - */ | |
| -export function useGetFulfillmentOrderItemOrderItemId< | |
| - TData = GetFulfillmentOrderItemOrderItemId["response"], | |
| - TQueryData = GetFulfillmentOrderItemOrderItemId["response"], | |
| - TQueryKey extends QueryKey = GetFulfillmentOrderItemOrderItemIdQueryKey, | |
| ->( | |
| - orderItemId: GetFulfillmentOrderItemOrderItemIdPathParams["order_item_id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetFulfillmentOrderItemOrderItemId["response"], | |
| - GetFulfillmentOrderItemOrderItemId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetFulfillmentOrderItemOrderItemId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetFulfillmentOrderItemOrderItemId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getFulfillmentOrderItemOrderItemIdQueryKey(orderItemId); | |
| - const query = useQuery({ | |
| - ...(getFulfillmentOrderItemOrderItemIdQueryOptions( | |
| - orderItemId, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetFulfillmentOrderItemOrderItemId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getFulfillmentOrderItemOrderItemIdSuspenseQueryKey = ( | |
| - orderItemId: GetFulfillmentOrderItemOrderItemIdPathParams["order_item_id"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/fulfillment/order-item/:order_item_id", | |
| - params: { orderItemId: orderItemId }, | |
| - }, | |
| - ] as const; | |
| -export type GetFulfillmentOrderItemOrderItemIdSuspenseQueryKey = ReturnType< | |
| - typeof getFulfillmentOrderItemOrderItemIdSuspenseQueryKey | |
| ->; | |
| -export function getFulfillmentOrderItemOrderItemIdSuspenseQueryOptions( | |
| - orderItemId: GetFulfillmentOrderItemOrderItemIdPathParams["order_item_id"], | |
| - options: GetFulfillmentOrderItemOrderItemId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getFulfillmentOrderItemOrderItemIdSuspenseQueryKey(orderItemId); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetFulfillmentOrderItemOrderItemId["data"], | |
| - GetFulfillmentOrderItemOrderItemId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/fulfillment/order-item/${orderItemId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get fulfillment by order item ID | |
| - * @summary Get fulfillment by order item ID | |
| - * @link /fulfillment/order-item/:order_item_id | |
| - */ | |
| -export function useGetFulfillmentOrderItemOrderItemIdSuspense< | |
| - TData = GetFulfillmentOrderItemOrderItemId["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetFulfillmentOrderItemOrderItemIdSuspenseQueryKey, | |
| ->( | |
| - orderItemId: GetFulfillmentOrderItemOrderItemIdPathParams["order_item_id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetFulfillmentOrderItemOrderItemId["response"], | |
| - GetFulfillmentOrderItemOrderItemId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetFulfillmentOrderItemOrderItemId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetFulfillmentOrderItemOrderItemId["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getFulfillmentOrderItemOrderItemIdSuspenseQueryKey(orderItemId); | |
| - const query = useSuspenseQuery({ | |
| - ...(getFulfillmentOrderItemOrderItemIdSuspenseQueryOptions( | |
| - orderItemId, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetFulfillmentOrderItemOrderItemId["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetHealth.ts b/src/phoenix-generated/hooks/useGetHealth.ts | |
| deleted file mode 100644 | |
| index 595c4cf2..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetHealth.ts | |
| +++ /dev/null | |
| @@ -1,143 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { GetHealthQueryResponse } from "../types/GetHealth"; | |
| - | |
| -type GetHealthClient = typeof client<GetHealthQueryResponse, Error, never>; | |
| -type GetHealth = { | |
| - data: GetHealthQueryResponse; | |
| - error: Error; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetHealthQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetHealthClient>[0]>; | |
| - return: Awaited<ReturnType<GetHealthClient>>; | |
| - }; | |
| -}; | |
| -export const getHealthQueryKey = () => [{ url: "/health" }] as const; | |
| -export type GetHealthQueryKey = ReturnType<typeof getHealthQueryKey>; | |
| -export function getHealthQueryOptions( | |
| - options: GetHealth["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getHealthQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetHealth["data"], GetHealth["error"]>({ | |
| - method: "get", | |
| - url: `/health`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Returns the health status of the API | |
| - * @summary Health check | |
| - * @link /health | |
| - */ | |
| -export function useGetHealth< | |
| - TData = GetHealth["response"], | |
| - TQueryData = GetHealth["response"], | |
| - TQueryKey extends QueryKey = GetHealthQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetHealth["response"], | |
| - GetHealth["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetHealth["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetHealth["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getHealthQueryKey(); | |
| - const query = useQuery({ | |
| - ...(getHealthQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetHealth["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getHealthSuspenseQueryKey = () => [{ url: "/health" }] as const; | |
| -export type GetHealthSuspenseQueryKey = ReturnType< | |
| - typeof getHealthSuspenseQueryKey | |
| ->; | |
| -export function getHealthSuspenseQueryOptions( | |
| - options: GetHealth["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getHealthSuspenseQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetHealth["data"], GetHealth["error"]>({ | |
| - method: "get", | |
| - url: `/health`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Returns the health status of the API | |
| - * @summary Health check | |
| - * @link /health | |
| - */ | |
| -export function useGetHealthSuspense< | |
| - TData = GetHealth["response"], | |
| - TQueryKey extends QueryKey = GetHealthSuspenseQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetHealth["response"], | |
| - GetHealth["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetHealth["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetHealth["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getHealthSuspenseQueryKey(); | |
| - const query = useSuspenseQuery({ | |
| - ...(getHealthSuspenseQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetHealth["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetLoyaltyCustomer.ts b/src/phoenix-generated/hooks/useGetLoyaltyCustomer.ts | |
| deleted file mode 100644 | |
| index 6cb9cfa1..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetLoyaltyCustomer.ts | |
| +++ /dev/null | |
| @@ -1,180 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetLoyaltyCustomer400, | |
| - GetLoyaltyCustomer401, | |
| - GetLoyaltyCustomer404, | |
| - GetLoyaltyCustomer500, | |
| - GetLoyaltyCustomerPathParams, | |
| - GetLoyaltyCustomerQueryResponse, | |
| -} from "../types/GetLoyaltyCustomer"; | |
| - | |
| -type GetLoyaltyCustomerClient = typeof client< | |
| - GetLoyaltyCustomerQueryResponse, | |
| - | GetLoyaltyCustomer400 | |
| - | GetLoyaltyCustomer401 | |
| - | GetLoyaltyCustomer404 | |
| - | GetLoyaltyCustomer500, | |
| - never | |
| ->; | |
| -type GetLoyaltyCustomer = { | |
| - data: GetLoyaltyCustomerQueryResponse; | |
| - error: | |
| - | GetLoyaltyCustomer400 | |
| - | GetLoyaltyCustomer401 | |
| - | GetLoyaltyCustomer404 | |
| - | GetLoyaltyCustomer500; | |
| - request: never; | |
| - pathParams: GetLoyaltyCustomerPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetLoyaltyCustomerQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetLoyaltyCustomerClient>[0]>; | |
| - return: Awaited<ReturnType<GetLoyaltyCustomerClient>>; | |
| - }; | |
| -}; | |
| -export const getLoyaltyCustomerQueryKey = ( | |
| - id: GetLoyaltyCustomerPathParams["id"], | |
| -) => [{ url: "/loyalty-customer/:id", params: { id: id } }] as const; | |
| -export type GetLoyaltyCustomerQueryKey = ReturnType< | |
| - typeof getLoyaltyCustomerQueryKey | |
| ->; | |
| -export function getLoyaltyCustomerQueryOptions( | |
| - id: GetLoyaltyCustomerPathParams["id"], | |
| - options: GetLoyaltyCustomer["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getLoyaltyCustomerQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetLoyaltyCustomer["data"], | |
| - GetLoyaltyCustomer["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/loyalty-customer/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a loyalty customer | |
| - * @summary Get loyalty customer | |
| - * @link /loyalty-customer/:id | |
| - */ | |
| -export function useGetLoyaltyCustomer< | |
| - TData = GetLoyaltyCustomer["response"], | |
| - TQueryData = GetLoyaltyCustomer["response"], | |
| - TQueryKey extends QueryKey = GetLoyaltyCustomerQueryKey, | |
| ->( | |
| - id: GetLoyaltyCustomerPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetLoyaltyCustomer["response"], | |
| - GetLoyaltyCustomer["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetLoyaltyCustomer["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetLoyaltyCustomer["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getLoyaltyCustomerQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getLoyaltyCustomerQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetLoyaltyCustomer["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getLoyaltyCustomerSuspenseQueryKey = ( | |
| - id: GetLoyaltyCustomerPathParams["id"], | |
| -) => [{ url: "/loyalty-customer/:id", params: { id: id } }] as const; | |
| -export type GetLoyaltyCustomerSuspenseQueryKey = ReturnType< | |
| - typeof getLoyaltyCustomerSuspenseQueryKey | |
| ->; | |
| -export function getLoyaltyCustomerSuspenseQueryOptions( | |
| - id: GetLoyaltyCustomerPathParams["id"], | |
| - options: GetLoyaltyCustomer["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getLoyaltyCustomerSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetLoyaltyCustomer["data"], | |
| - GetLoyaltyCustomer["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/loyalty-customer/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a loyalty customer | |
| - * @summary Get loyalty customer | |
| - * @link /loyalty-customer/:id | |
| - */ | |
| -export function useGetLoyaltyCustomerSuspense< | |
| - TData = GetLoyaltyCustomer["response"], | |
| - TQueryKey extends QueryKey = GetLoyaltyCustomerSuspenseQueryKey, | |
| ->( | |
| - id: GetLoyaltyCustomerPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetLoyaltyCustomer["response"], | |
| - GetLoyaltyCustomer["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetLoyaltyCustomer["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetLoyaltyCustomer["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getLoyaltyCustomerSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getLoyaltyCustomerSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetLoyaltyCustomer["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetLoyaltyCustomerIdPoints.ts b/src/phoenix-generated/hooks/useGetLoyaltyCustomerIdPoints.ts | |
| deleted file mode 100644 | |
| index 86e3f03d..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetLoyaltyCustomerIdPoints.ts | |
| +++ /dev/null | |
| @@ -1,201 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetLoyaltyCustomerIdPoints400, | |
| - GetLoyaltyCustomerIdPoints401, | |
| - GetLoyaltyCustomerIdPoints404, | |
| - GetLoyaltyCustomerIdPoints500, | |
| - GetLoyaltyCustomerIdPointsPathParams, | |
| - GetLoyaltyCustomerIdPointsQueryParams, | |
| - GetLoyaltyCustomerIdPointsQueryResponse, | |
| -} from "../types/GetLoyaltyCustomerIdPoints"; | |
| - | |
| -type GetLoyaltyCustomerIdPointsClient = typeof client< | |
| - GetLoyaltyCustomerIdPointsQueryResponse, | |
| - | GetLoyaltyCustomerIdPoints400 | |
| - | GetLoyaltyCustomerIdPoints401 | |
| - | GetLoyaltyCustomerIdPoints404 | |
| - | GetLoyaltyCustomerIdPoints500, | |
| - never | |
| ->; | |
| -type GetLoyaltyCustomerIdPoints = { | |
| - data: GetLoyaltyCustomerIdPointsQueryResponse; | |
| - error: | |
| - | GetLoyaltyCustomerIdPoints400 | |
| - | GetLoyaltyCustomerIdPoints401 | |
| - | GetLoyaltyCustomerIdPoints404 | |
| - | GetLoyaltyCustomerIdPoints500; | |
| - request: never; | |
| - pathParams: GetLoyaltyCustomerIdPointsPathParams; | |
| - queryParams: GetLoyaltyCustomerIdPointsQueryParams; | |
| - headerParams: never; | |
| - response: GetLoyaltyCustomerIdPointsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetLoyaltyCustomerIdPointsClient>[0]>; | |
| - return: Awaited<ReturnType<GetLoyaltyCustomerIdPointsClient>>; | |
| - }; | |
| -}; | |
| -export const getLoyaltyCustomerIdPointsQueryKey = ( | |
| - id: GetLoyaltyCustomerIdPointsPathParams["id"], | |
| - params?: GetLoyaltyCustomerIdPoints["queryParams"], | |
| -) => | |
| - [ | |
| - { url: "/loyalty-customer/:id/points", params: { id: id } }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetLoyaltyCustomerIdPointsQueryKey = ReturnType< | |
| - typeof getLoyaltyCustomerIdPointsQueryKey | |
| ->; | |
| -export function getLoyaltyCustomerIdPointsQueryOptions( | |
| - id: GetLoyaltyCustomerIdPointsPathParams["id"], | |
| - params?: GetLoyaltyCustomerIdPoints["queryParams"], | |
| - options: GetLoyaltyCustomerIdPoints["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getLoyaltyCustomerIdPointsQueryKey(id, params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetLoyaltyCustomerIdPoints["data"], | |
| - GetLoyaltyCustomerIdPoints["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/loyalty-customer/${id}/points`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get the total points for a loyalty customer | |
| - * @summary Get loyalty customer points | |
| - * @link /loyalty-customer/:id/points | |
| - */ | |
| -export function useGetLoyaltyCustomerIdPoints< | |
| - TData = GetLoyaltyCustomerIdPoints["response"], | |
| - TQueryData = GetLoyaltyCustomerIdPoints["response"], | |
| - TQueryKey extends QueryKey = GetLoyaltyCustomerIdPointsQueryKey, | |
| ->( | |
| - id: GetLoyaltyCustomerIdPointsPathParams["id"], | |
| - params?: GetLoyaltyCustomerIdPoints["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetLoyaltyCustomerIdPoints["response"], | |
| - GetLoyaltyCustomerIdPoints["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetLoyaltyCustomerIdPoints["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetLoyaltyCustomerIdPoints["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getLoyaltyCustomerIdPointsQueryKey(id, params); | |
| - const query = useQuery({ | |
| - ...(getLoyaltyCustomerIdPointsQueryOptions( | |
| - id, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetLoyaltyCustomerIdPoints["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getLoyaltyCustomerIdPointsSuspenseQueryKey = ( | |
| - id: GetLoyaltyCustomerIdPointsPathParams["id"], | |
| - params?: GetLoyaltyCustomerIdPoints["queryParams"], | |
| -) => | |
| - [ | |
| - { url: "/loyalty-customer/:id/points", params: { id: id } }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetLoyaltyCustomerIdPointsSuspenseQueryKey = ReturnType< | |
| - typeof getLoyaltyCustomerIdPointsSuspenseQueryKey | |
| ->; | |
| -export function getLoyaltyCustomerIdPointsSuspenseQueryOptions( | |
| - id: GetLoyaltyCustomerIdPointsPathParams["id"], | |
| - params?: GetLoyaltyCustomerIdPoints["queryParams"], | |
| - options: GetLoyaltyCustomerIdPoints["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getLoyaltyCustomerIdPointsSuspenseQueryKey(id, params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetLoyaltyCustomerIdPoints["data"], | |
| - GetLoyaltyCustomerIdPoints["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/loyalty-customer/${id}/points`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get the total points for a loyalty customer | |
| - * @summary Get loyalty customer points | |
| - * @link /loyalty-customer/:id/points | |
| - */ | |
| -export function useGetLoyaltyCustomerIdPointsSuspense< | |
| - TData = GetLoyaltyCustomerIdPoints["response"], | |
| - TQueryKey extends QueryKey = GetLoyaltyCustomerIdPointsSuspenseQueryKey, | |
| ->( | |
| - id: GetLoyaltyCustomerIdPointsPathParams["id"], | |
| - params?: GetLoyaltyCustomerIdPoints["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetLoyaltyCustomerIdPoints["response"], | |
| - GetLoyaltyCustomerIdPoints["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetLoyaltyCustomerIdPoints["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetLoyaltyCustomerIdPoints["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getLoyaltyCustomerIdPointsSuspenseQueryKey(id, params); | |
| - const query = useSuspenseQuery({ | |
| - ...(getLoyaltyCustomerIdPointsSuspenseQueryOptions( | |
| - id, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetLoyaltyCustomerIdPoints["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetOrderItemDecision.ts b/src/phoenix-generated/hooks/useGetOrderItemDecision.ts | |
| deleted file mode 100644 | |
| index ab00e8f8..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetOrderItemDecision.ts | |
| +++ /dev/null | |
| @@ -1,180 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetOrderItemDecision400, | |
| - GetOrderItemDecision401, | |
| - GetOrderItemDecision404, | |
| - GetOrderItemDecision500, | |
| - GetOrderItemDecisionPathParams, | |
| - GetOrderItemDecisionQueryResponse, | |
| -} from "../types/GetOrderItemDecision"; | |
| - | |
| -type GetOrderItemDecisionClient = typeof client< | |
| - GetOrderItemDecisionQueryResponse, | |
| - | GetOrderItemDecision400 | |
| - | GetOrderItemDecision401 | |
| - | GetOrderItemDecision404 | |
| - | GetOrderItemDecision500, | |
| - never | |
| ->; | |
| -type GetOrderItemDecision = { | |
| - data: GetOrderItemDecisionQueryResponse; | |
| - error: | |
| - | GetOrderItemDecision400 | |
| - | GetOrderItemDecision401 | |
| - | GetOrderItemDecision404 | |
| - | GetOrderItemDecision500; | |
| - request: never; | |
| - pathParams: GetOrderItemDecisionPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetOrderItemDecisionQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetOrderItemDecisionClient>[0]>; | |
| - return: Awaited<ReturnType<GetOrderItemDecisionClient>>; | |
| - }; | |
| -}; | |
| -export const getOrderItemDecisionQueryKey = ( | |
| - id: GetOrderItemDecisionPathParams["id"], | |
| -) => [{ url: "/order-item-decisions/:id", params: { id: id } }] as const; | |
| -export type GetOrderItemDecisionQueryKey = ReturnType< | |
| - typeof getOrderItemDecisionQueryKey | |
| ->; | |
| -export function getOrderItemDecisionQueryOptions( | |
| - id: GetOrderItemDecisionPathParams["id"], | |
| - options: GetOrderItemDecision["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getOrderItemDecisionQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetOrderItemDecision["data"], | |
| - GetOrderItemDecision["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/order-item-decisions/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get an order item decision by ID | |
| - * @summary Get order item decision | |
| - * @link /order-item-decisions/:id | |
| - */ | |
| -export function useGetOrderItemDecision< | |
| - TData = GetOrderItemDecision["response"], | |
| - TQueryData = GetOrderItemDecision["response"], | |
| - TQueryKey extends QueryKey = GetOrderItemDecisionQueryKey, | |
| ->( | |
| - id: GetOrderItemDecisionPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetOrderItemDecision["response"], | |
| - GetOrderItemDecision["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetOrderItemDecision["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetOrderItemDecision["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getOrderItemDecisionQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getOrderItemDecisionQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetOrderItemDecision["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getOrderItemDecisionSuspenseQueryKey = ( | |
| - id: GetOrderItemDecisionPathParams["id"], | |
| -) => [{ url: "/order-item-decisions/:id", params: { id: id } }] as const; | |
| -export type GetOrderItemDecisionSuspenseQueryKey = ReturnType< | |
| - typeof getOrderItemDecisionSuspenseQueryKey | |
| ->; | |
| -export function getOrderItemDecisionSuspenseQueryOptions( | |
| - id: GetOrderItemDecisionPathParams["id"], | |
| - options: GetOrderItemDecision["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getOrderItemDecisionSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetOrderItemDecision["data"], | |
| - GetOrderItemDecision["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/order-item-decisions/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get an order item decision by ID | |
| - * @summary Get order item decision | |
| - * @link /order-item-decisions/:id | |
| - */ | |
| -export function useGetOrderItemDecisionSuspense< | |
| - TData = GetOrderItemDecision["response"], | |
| - TQueryKey extends QueryKey = GetOrderItemDecisionSuspenseQueryKey, | |
| ->( | |
| - id: GetOrderItemDecisionPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetOrderItemDecision["response"], | |
| - GetOrderItemDecision["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetOrderItemDecision["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetOrderItemDecision["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getOrderItemDecisionSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getOrderItemDecisionSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetOrderItemDecision["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetOrderItemDecisionsTransactionItemTransactionItemId.ts b/src/phoenix-generated/hooks/useGetOrderItemDecisionsTransactionItemTransactionItemId.ts | |
| deleted file mode 100644 | |
| index 92e119be..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetOrderItemDecisionsTransactionItemTransactionItemId.ts | |
| +++ /dev/null | |
| @@ -1,227 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId400, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId401, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId404, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId500, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemIdQueryResponse, | |
| -} from "../types/GetOrderItemDecisionsTransactionItemTransactionItemId"; | |
| - | |
| -type GetOrderItemDecisionsTransactionItemTransactionItemIdClient = | |
| - typeof client< | |
| - GetOrderItemDecisionsTransactionItemTransactionItemIdQueryResponse, | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId400 | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId401 | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId404 | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId500, | |
| - never | |
| - >; | |
| -type GetOrderItemDecisionsTransactionItemTransactionItemId = { | |
| - data: GetOrderItemDecisionsTransactionItemTransactionItemIdQueryResponse; | |
| - error: | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId400 | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId401 | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId404 | |
| - | GetOrderItemDecisionsTransactionItemTransactionItemId500; | |
| - request: never; | |
| - pathParams: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetOrderItemDecisionsTransactionItemTransactionItemIdQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetOrderItemDecisionsTransactionItemTransactionItemIdClient>[0] | |
| - >; | |
| - return: Awaited< | |
| - ReturnType<GetOrderItemDecisionsTransactionItemTransactionItemIdClient> | |
| - >; | |
| - }; | |
| -}; | |
| -export const getOrderItemDecisionsTransactionItemTransactionItemIdQueryKey = ( | |
| - transactionItemId: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams["transaction_item_id"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/order-item-decisions/transaction-item/:transaction_item_id", | |
| - params: { transactionItemId: transactionItemId }, | |
| - }, | |
| - ] as const; | |
| -export type GetOrderItemDecisionsTransactionItemTransactionItemIdQueryKey = | |
| - ReturnType< | |
| - typeof getOrderItemDecisionsTransactionItemTransactionItemIdQueryKey | |
| - >; | |
| -export function getOrderItemDecisionsTransactionItemTransactionItemIdQueryOptions( | |
| - transactionItemId: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams["transaction_item_id"], | |
| - options: GetOrderItemDecisionsTransactionItemTransactionItemId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getOrderItemDecisionsTransactionItemTransactionItemIdQueryKey( | |
| - transactionItemId, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["data"], | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/order-item-decisions/transaction-item/${transactionItemId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get all order item decisions for a specific transaction item | |
| - * @summary Get order item decisions by transaction item | |
| - * @link /order-item-decisions/transaction-item/:transaction_item_id | |
| - */ | |
| -export function useGetOrderItemDecisionsTransactionItemTransactionItemId< | |
| - TData = GetOrderItemDecisionsTransactionItemTransactionItemId["response"], | |
| - TQueryData = GetOrderItemDecisionsTransactionItemTransactionItemId["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetOrderItemDecisionsTransactionItemTransactionItemIdQueryKey, | |
| ->( | |
| - transactionItemId: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams["transaction_item_id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["response"], | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetOrderItemDecisionsTransactionItemTransactionItemId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult< | |
| - TData, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getOrderItemDecisionsTransactionItemTransactionItemIdQueryKey( | |
| - transactionItemId, | |
| - ); | |
| - const query = useQuery({ | |
| - ...(getOrderItemDecisionsTransactionItemTransactionItemIdQueryOptions( | |
| - transactionItemId, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult< | |
| - TData, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryKey = | |
| - ( | |
| - transactionItemId: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams["transaction_item_id"], | |
| - ) => | |
| - [ | |
| - { | |
| - url: "/order-item-decisions/transaction-item/:transaction_item_id", | |
| - params: { transactionItemId: transactionItemId }, | |
| - }, | |
| - ] as const; | |
| -export type GetOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryKey = | |
| - ReturnType< | |
| - typeof getOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryKey | |
| - >; | |
| -export function getOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryOptions( | |
| - transactionItemId: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams["transaction_item_id"], | |
| - options: GetOrderItemDecisionsTransactionItemTransactionItemId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryKey( | |
| - transactionItemId, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["data"], | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/order-item-decisions/transaction-item/${transactionItemId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get all order item decisions for a specific transaction item | |
| - * @summary Get order item decisions by transaction item | |
| - * @link /order-item-decisions/transaction-item/:transaction_item_id | |
| - */ | |
| -export function useGetOrderItemDecisionsTransactionItemTransactionItemIdSuspense< | |
| - TData = GetOrderItemDecisionsTransactionItemTransactionItemId["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryKey, | |
| ->( | |
| - transactionItemId: GetOrderItemDecisionsTransactionItemTransactionItemIdPathParams["transaction_item_id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["response"], | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetOrderItemDecisionsTransactionItemTransactionItemId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryKey( | |
| - transactionItemId, | |
| - ); | |
| - const query = useSuspenseQuery({ | |
| - ...(getOrderItemDecisionsTransactionItemTransactionItemIdSuspenseQueryOptions( | |
| - transactionItemId, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetOrderItemDecisionsTransactionItemTransactionItemId["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetProducts.ts b/src/phoenix-generated/hooks/useGetProducts.ts | |
| deleted file mode 100644 | |
| index 20cdd5ff..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetProducts.ts | |
| +++ /dev/null | |
| @@ -1,166 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetProducts400, | |
| - GetProducts401, | |
| - GetProducts422, | |
| - GetProducts500, | |
| - GetProductsQueryParams, | |
| - GetProductsQueryResponse, | |
| -} from "../types/GetProducts"; | |
| - | |
| -type GetProductsClient = typeof client< | |
| - GetProductsQueryResponse, | |
| - GetProducts400 | GetProducts401 | GetProducts422 | GetProducts500, | |
| - never | |
| ->; | |
| -type GetProducts = { | |
| - data: GetProductsQueryResponse; | |
| - error: GetProducts400 | GetProducts401 | GetProducts422 | GetProducts500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: GetProductsQueryParams; | |
| - headerParams: never; | |
| - response: GetProductsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetProductsClient>[0]>; | |
| - return: Awaited<ReturnType<GetProductsClient>>; | |
| - }; | |
| -}; | |
| -export const getProductsQueryKey = (params: GetProducts["queryParams"]) => | |
| - [{ url: "/products" }, ...(params ? [params] : [])] as const; | |
| -export type GetProductsQueryKey = ReturnType<typeof getProductsQueryKey>; | |
| -export function getProductsQueryOptions( | |
| - params: GetProducts["queryParams"], | |
| - options: GetProducts["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getProductsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetProducts["data"], GetProducts["error"]>({ | |
| - method: "get", | |
| - url: `/products`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List products for a storefront | |
| - * @summary List products | |
| - * @link /products | |
| - */ | |
| -export function useGetProducts< | |
| - TData = GetProducts["response"], | |
| - TQueryData = GetProducts["response"], | |
| - TQueryKey extends QueryKey = GetProductsQueryKey, | |
| ->( | |
| - params: GetProducts["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetProducts["response"], | |
| - GetProducts["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetProducts["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetProducts["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getProductsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(getProductsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetProducts["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getProductsSuspenseQueryKey = ( | |
| - params: GetProducts["queryParams"], | |
| -) => [{ url: "/products" }, ...(params ? [params] : [])] as const; | |
| -export type GetProductsSuspenseQueryKey = ReturnType< | |
| - typeof getProductsSuspenseQueryKey | |
| ->; | |
| -export function getProductsSuspenseQueryOptions( | |
| - params: GetProducts["queryParams"], | |
| - options: GetProducts["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getProductsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client<GetProducts["data"], GetProducts["error"]>({ | |
| - method: "get", | |
| - url: `/products`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List products for a storefront | |
| - * @summary List products | |
| - * @link /products | |
| - */ | |
| -export function useGetProductsSuspense< | |
| - TData = GetProducts["response"], | |
| - TQueryKey extends QueryKey = GetProductsSuspenseQueryKey, | |
| ->( | |
| - params: GetProducts["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetProducts["response"], | |
| - GetProducts["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetProducts["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetProducts["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getProductsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(getProductsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetProducts["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetProductsProductId.ts b/src/phoenix-generated/hooks/useGetProductsProductId.ts | |
| deleted file mode 100644 | |
| index dd0027fe..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetProductsProductId.ts | |
| +++ /dev/null | |
| @@ -1,201 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetProductsProductId400, | |
| - GetProductsProductId401, | |
| - GetProductsProductId404, | |
| - GetProductsProductId500, | |
| - GetProductsProductIdPathParams, | |
| - GetProductsProductIdQueryParams, | |
| - GetProductsProductIdQueryResponse, | |
| -} from "../types/GetProductsProductId"; | |
| - | |
| -type GetProductsProductIdClient = typeof client< | |
| - GetProductsProductIdQueryResponse, | |
| - | GetProductsProductId400 | |
| - | GetProductsProductId401 | |
| - | GetProductsProductId404 | |
| - | GetProductsProductId500, | |
| - never | |
| ->; | |
| -type GetProductsProductId = { | |
| - data: GetProductsProductIdQueryResponse; | |
| - error: | |
| - | GetProductsProductId400 | |
| - | GetProductsProductId401 | |
| - | GetProductsProductId404 | |
| - | GetProductsProductId500; | |
| - request: never; | |
| - pathParams: GetProductsProductIdPathParams; | |
| - queryParams: GetProductsProductIdQueryParams; | |
| - headerParams: never; | |
| - response: GetProductsProductIdQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetProductsProductIdClient>[0]>; | |
| - return: Awaited<ReturnType<GetProductsProductIdClient>>; | |
| - }; | |
| -}; | |
| -export const getProductsProductIdQueryKey = ( | |
| - productId: GetProductsProductIdPathParams["product_id"], | |
| - params: GetProductsProductId["queryParams"], | |
| -) => | |
| - [ | |
| - { url: "/products/:product_id", params: { productId: productId } }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetProductsProductIdQueryKey = ReturnType< | |
| - typeof getProductsProductIdQueryKey | |
| ->; | |
| -export function getProductsProductIdQueryOptions( | |
| - productId: GetProductsProductIdPathParams["product_id"], | |
| - params: GetProductsProductId["queryParams"], | |
| - options: GetProductsProductId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getProductsProductIdQueryKey(productId, params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetProductsProductId["data"], | |
| - GetProductsProductId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/products/${productId}`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get product by ID | |
| - * @summary Get product | |
| - * @link /products/:product_id | |
| - */ | |
| -export function useGetProductsProductId< | |
| - TData = GetProductsProductId["response"], | |
| - TQueryData = GetProductsProductId["response"], | |
| - TQueryKey extends QueryKey = GetProductsProductIdQueryKey, | |
| ->( | |
| - productId: GetProductsProductIdPathParams["product_id"], | |
| - params: GetProductsProductId["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetProductsProductId["response"], | |
| - GetProductsProductId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetProductsProductId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetProductsProductId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getProductsProductIdQueryKey(productId, params); | |
| - const query = useQuery({ | |
| - ...(getProductsProductIdQueryOptions( | |
| - productId, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetProductsProductId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getProductsProductIdSuspenseQueryKey = ( | |
| - productId: GetProductsProductIdPathParams["product_id"], | |
| - params: GetProductsProductId["queryParams"], | |
| -) => | |
| - [ | |
| - { url: "/products/:product_id", params: { productId: productId } }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetProductsProductIdSuspenseQueryKey = ReturnType< | |
| - typeof getProductsProductIdSuspenseQueryKey | |
| ->; | |
| -export function getProductsProductIdSuspenseQueryOptions( | |
| - productId: GetProductsProductIdPathParams["product_id"], | |
| - params: GetProductsProductId["queryParams"], | |
| - options: GetProductsProductId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getProductsProductIdSuspenseQueryKey(productId, params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetProductsProductId["data"], | |
| - GetProductsProductId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/products/${productId}`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get product by ID | |
| - * @summary Get product | |
| - * @link /products/:product_id | |
| - */ | |
| -export function useGetProductsProductIdSuspense< | |
| - TData = GetProductsProductId["response"], | |
| - TQueryKey extends QueryKey = GetProductsProductIdSuspenseQueryKey, | |
| ->( | |
| - productId: GetProductsProductIdPathParams["product_id"], | |
| - params: GetProductsProductId["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetProductsProductId["response"], | |
| - GetProductsProductId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetProductsProductId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetProductsProductId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getProductsProductIdSuspenseQueryKey(productId, params); | |
| - const query = useSuspenseQuery({ | |
| - ...(getProductsProductIdSuspenseQueryOptions( | |
| - productId, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetProductsProductId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetProductsStorefrontStorefrontIdPathPath.ts b/src/phoenix-generated/hooks/useGetProductsStorefrontStorefrontIdPathPath.ts | |
| deleted file mode 100644 | |
| index bd045dc9..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetProductsStorefrontStorefrontIdPathPath.ts | |
| +++ /dev/null | |
| @@ -1,246 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetProductsStorefrontStorefrontIdPathPath400, | |
| - GetProductsStorefrontStorefrontIdPathPath401, | |
| - GetProductsStorefrontStorefrontIdPathPath404, | |
| - GetProductsStorefrontStorefrontIdPathPath500, | |
| - GetProductsStorefrontStorefrontIdPathPathPathParams, | |
| - GetProductsStorefrontStorefrontIdPathPathQueryParams, | |
| - GetProductsStorefrontStorefrontIdPathPathQueryResponse, | |
| -} from "../types/GetProductsStorefrontStorefrontIdPathPath"; | |
| - | |
| -type GetProductsStorefrontStorefrontIdPathPathClient = typeof client< | |
| - GetProductsStorefrontStorefrontIdPathPathQueryResponse, | |
| - | GetProductsStorefrontStorefrontIdPathPath400 | |
| - | GetProductsStorefrontStorefrontIdPathPath401 | |
| - | GetProductsStorefrontStorefrontIdPathPath404 | |
| - | GetProductsStorefrontStorefrontIdPathPath500, | |
| - never | |
| ->; | |
| -type GetProductsStorefrontStorefrontIdPathPath = { | |
| - data: GetProductsStorefrontStorefrontIdPathPathQueryResponse; | |
| - error: | |
| - | GetProductsStorefrontStorefrontIdPathPath400 | |
| - | GetProductsStorefrontStorefrontIdPathPath401 | |
| - | GetProductsStorefrontStorefrontIdPathPath404 | |
| - | GetProductsStorefrontStorefrontIdPathPath500; | |
| - request: never; | |
| - pathParams: GetProductsStorefrontStorefrontIdPathPathPathParams; | |
| - queryParams: GetProductsStorefrontStorefrontIdPathPathQueryParams; | |
| - headerParams: never; | |
| - response: GetProductsStorefrontStorefrontIdPathPathQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetProductsStorefrontStorefrontIdPathPathClient>[0] | |
| - >; | |
| - return: Awaited< | |
| - ReturnType<GetProductsStorefrontStorefrontIdPathPathClient> | |
| - >; | |
| - }; | |
| -}; | |
| -export const getProductsStorefrontStorefrontIdPathPathQueryKey = ( | |
| - storefrontId: GetProductsStorefrontStorefrontIdPathPathPathParams["storefront_id"], | |
| - path: GetProductsStorefrontStorefrontIdPathPathPathParams["path"], | |
| - params: GetProductsStorefrontStorefrontIdPathPath["queryParams"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/products/storefront/:storefront_id/path/:path", | |
| - params: { storefrontId: storefrontId, path: path }, | |
| - }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetProductsStorefrontStorefrontIdPathPathQueryKey = ReturnType< | |
| - typeof getProductsStorefrontStorefrontIdPathPathQueryKey | |
| ->; | |
| -export function getProductsStorefrontStorefrontIdPathPathQueryOptions( | |
| - storefrontId: GetProductsStorefrontStorefrontIdPathPathPathParams["storefront_id"], | |
| - path: GetProductsStorefrontStorefrontIdPathPathPathParams["path"], | |
| - params: GetProductsStorefrontStorefrontIdPathPath["queryParams"], | |
| - options: GetProductsStorefrontStorefrontIdPathPath["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getProductsStorefrontStorefrontIdPathPathQueryKey( | |
| - storefrontId, | |
| - path, | |
| - params, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetProductsStorefrontStorefrontIdPathPath["data"], | |
| - GetProductsStorefrontStorefrontIdPathPath["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/products/storefront/${storefrontId}/path/${path}`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get product by storefront id and path | |
| - * @summary Get product by storefront id and path | |
| - * @link /products/storefront/:storefront_id/path/:path | |
| - */ | |
| -export function useGetProductsStorefrontStorefrontIdPathPath< | |
| - TData = GetProductsStorefrontStorefrontIdPathPath["response"], | |
| - TQueryData = GetProductsStorefrontStorefrontIdPathPath["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetProductsStorefrontStorefrontIdPathPathQueryKey, | |
| ->( | |
| - storefrontId: GetProductsStorefrontStorefrontIdPathPathPathParams["storefront_id"], | |
| - path: GetProductsStorefrontStorefrontIdPathPathPathParams["path"], | |
| - params: GetProductsStorefrontStorefrontIdPathPath["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetProductsStorefrontStorefrontIdPathPath["response"], | |
| - GetProductsStorefrontStorefrontIdPathPath["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetProductsStorefrontStorefrontIdPathPath["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetProductsStorefrontStorefrontIdPathPath["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getProductsStorefrontStorefrontIdPathPathQueryKey( | |
| - storefrontId, | |
| - path, | |
| - params, | |
| - ); | |
| - const query = useQuery({ | |
| - ...(getProductsStorefrontStorefrontIdPathPathQueryOptions( | |
| - storefrontId, | |
| - path, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult< | |
| - TData, | |
| - GetProductsStorefrontStorefrontIdPathPath["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getProductsStorefrontStorefrontIdPathPathSuspenseQueryKey = ( | |
| - storefrontId: GetProductsStorefrontStorefrontIdPathPathPathParams["storefront_id"], | |
| - path: GetProductsStorefrontStorefrontIdPathPathPathParams["path"], | |
| - params: GetProductsStorefrontStorefrontIdPathPath["queryParams"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/products/storefront/:storefront_id/path/:path", | |
| - params: { storefrontId: storefrontId, path: path }, | |
| - }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetProductsStorefrontStorefrontIdPathPathSuspenseQueryKey = | |
| - ReturnType<typeof getProductsStorefrontStorefrontIdPathPathSuspenseQueryKey>; | |
| -export function getProductsStorefrontStorefrontIdPathPathSuspenseQueryOptions( | |
| - storefrontId: GetProductsStorefrontStorefrontIdPathPathPathParams["storefront_id"], | |
| - path: GetProductsStorefrontStorefrontIdPathPathPathParams["path"], | |
| - params: GetProductsStorefrontStorefrontIdPathPath["queryParams"], | |
| - options: GetProductsStorefrontStorefrontIdPathPath["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getProductsStorefrontStorefrontIdPathPathSuspenseQueryKey( | |
| - storefrontId, | |
| - path, | |
| - params, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetProductsStorefrontStorefrontIdPathPath["data"], | |
| - GetProductsStorefrontStorefrontIdPathPath["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/products/storefront/${storefrontId}/path/${path}`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get product by storefront id and path | |
| - * @summary Get product by storefront id and path | |
| - * @link /products/storefront/:storefront_id/path/:path | |
| - */ | |
| -export function useGetProductsStorefrontStorefrontIdPathPathSuspense< | |
| - TData = GetProductsStorefrontStorefrontIdPathPath["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetProductsStorefrontStorefrontIdPathPathSuspenseQueryKey, | |
| ->( | |
| - storefrontId: GetProductsStorefrontStorefrontIdPathPathPathParams["storefront_id"], | |
| - path: GetProductsStorefrontStorefrontIdPathPathPathParams["path"], | |
| - params: GetProductsStorefrontStorefrontIdPathPath["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetProductsStorefrontStorefrontIdPathPath["response"], | |
| - GetProductsStorefrontStorefrontIdPathPath["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetProductsStorefrontStorefrontIdPathPath["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetProductsStorefrontStorefrontIdPathPath["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getProductsStorefrontStorefrontIdPathPathSuspenseQueryKey( | |
| - storefrontId, | |
| - path, | |
| - params, | |
| - ); | |
| - const query = useSuspenseQuery({ | |
| - ...(getProductsStorefrontStorefrontIdPathPathSuspenseQueryOptions( | |
| - storefrontId, | |
| - path, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetProductsStorefrontStorefrontIdPathPath["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStoreHoursEntitySalesChannelEntitySalesChannelId.ts b/src/phoenix-generated/hooks/useGetStoreHoursEntitySalesChannelEntitySalesChannelId.ts | |
| deleted file mode 100644 | |
| index a13099e3..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStoreHoursEntitySalesChannelEntitySalesChannelId.ts | |
| +++ /dev/null | |
| @@ -1,220 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId400, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId500, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelIdQueryResponse, | |
| -} from "../types/GetStoreHoursEntitySalesChannelEntitySalesChannelId"; | |
| - | |
| -type GetStoreHoursEntitySalesChannelEntitySalesChannelIdClient = typeof client< | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelIdQueryResponse, | |
| - | GetStoreHoursEntitySalesChannelEntitySalesChannelId400 | |
| - | GetStoreHoursEntitySalesChannelEntitySalesChannelId500, | |
| - never | |
| ->; | |
| -type GetStoreHoursEntitySalesChannelEntitySalesChannelId = { | |
| - data: GetStoreHoursEntitySalesChannelEntitySalesChannelIdQueryResponse; | |
| - error: | |
| - | GetStoreHoursEntitySalesChannelEntitySalesChannelId400 | |
| - | GetStoreHoursEntitySalesChannelEntitySalesChannelId500; | |
| - request: never; | |
| - pathParams: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStoreHoursEntitySalesChannelEntitySalesChannelIdQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetStoreHoursEntitySalesChannelEntitySalesChannelIdClient>[0] | |
| - >; | |
| - return: Awaited< | |
| - ReturnType<GetStoreHoursEntitySalesChannelEntitySalesChannelIdClient> | |
| - >; | |
| - }; | |
| -}; | |
| -export const getStoreHoursEntitySalesChannelEntitySalesChannelIdQueryKey = ( | |
| - entitySalesChannelId: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/store-hours/entity-sales-channel/:entity_sales_channel_id", | |
| - params: { entitySalesChannelId: entitySalesChannelId }, | |
| - }, | |
| - ] as const; | |
| -export type GetStoreHoursEntitySalesChannelEntitySalesChannelIdQueryKey = | |
| - ReturnType< | |
| - typeof getStoreHoursEntitySalesChannelEntitySalesChannelIdQueryKey | |
| - >; | |
| -export function getStoreHoursEntitySalesChannelEntitySalesChannelIdQueryOptions( | |
| - entitySalesChannelId: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"], | |
| - options: GetStoreHoursEntitySalesChannelEntitySalesChannelId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getStoreHoursEntitySalesChannelEntitySalesChannelIdQueryKey( | |
| - entitySalesChannelId, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["data"], | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/store-hours/entity-sales-channel/${entitySalesChannelId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get store hours for a specific entity sales channel | |
| - * @summary Get store hours by entity sales channel | |
| - * @link /store-hours/entity-sales-channel/:entity_sales_channel_id | |
| - */ | |
| -export function useGetStoreHoursEntitySalesChannelEntitySalesChannelId< | |
| - TData = GetStoreHoursEntitySalesChannelEntitySalesChannelId["response"], | |
| - TQueryData = GetStoreHoursEntitySalesChannelEntitySalesChannelId["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetStoreHoursEntitySalesChannelEntitySalesChannelIdQueryKey, | |
| ->( | |
| - entitySalesChannelId: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["response"], | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStoreHoursEntitySalesChannelEntitySalesChannelId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult< | |
| - TData, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStoreHoursEntitySalesChannelEntitySalesChannelIdQueryKey( | |
| - entitySalesChannelId, | |
| - ); | |
| - const query = useQuery({ | |
| - ...(getStoreHoursEntitySalesChannelEntitySalesChannelIdQueryOptions( | |
| - entitySalesChannelId, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult< | |
| - TData, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryKey = | |
| - ( | |
| - entitySalesChannelId: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"], | |
| - ) => | |
| - [ | |
| - { | |
| - url: "/store-hours/entity-sales-channel/:entity_sales_channel_id", | |
| - params: { entitySalesChannelId: entitySalesChannelId }, | |
| - }, | |
| - ] as const; | |
| -export type GetStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryKey = | |
| - ReturnType< | |
| - typeof getStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryKey | |
| - >; | |
| -export function getStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryOptions( | |
| - entitySalesChannelId: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"], | |
| - options: GetStoreHoursEntitySalesChannelEntitySalesChannelId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryKey( | |
| - entitySalesChannelId, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["data"], | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/store-hours/entity-sales-channel/${entitySalesChannelId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get store hours for a specific entity sales channel | |
| - * @summary Get store hours by entity sales channel | |
| - * @link /store-hours/entity-sales-channel/:entity_sales_channel_id | |
| - */ | |
| -export function useGetStoreHoursEntitySalesChannelEntitySalesChannelIdSuspense< | |
| - TData = GetStoreHoursEntitySalesChannelEntitySalesChannelId["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryKey, | |
| ->( | |
| - entitySalesChannelId: GetStoreHoursEntitySalesChannelEntitySalesChannelIdPathParams["entity_sales_channel_id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["response"], | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStoreHoursEntitySalesChannelEntitySalesChannelId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryKey( | |
| - entitySalesChannelId, | |
| - ); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStoreHoursEntitySalesChannelEntitySalesChannelIdSuspenseQueryOptions( | |
| - entitySalesChannelId, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetStoreHoursEntitySalesChannelEntitySalesChannelId["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontPagesPageid.ts b/src/phoenix-generated/hooks/useGetStorefrontPagesPageid.ts | |
| deleted file mode 100644 | |
| index b276dc04..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontPagesPageid.ts | |
| +++ /dev/null | |
| @@ -1,183 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontPagesPageid400, | |
| - GetStorefrontPagesPageid401, | |
| - GetStorefrontPagesPageid404, | |
| - GetStorefrontPagesPageid500, | |
| - GetStorefrontPagesPageidPathParams, | |
| - GetStorefrontPagesPageidQueryResponse, | |
| -} from "../types/GetStorefrontPagesPageid"; | |
| - | |
| -type GetStorefrontPagesPageidClient = typeof client< | |
| - GetStorefrontPagesPageidQueryResponse, | |
| - | GetStorefrontPagesPageid400 | |
| - | GetStorefrontPagesPageid401 | |
| - | GetStorefrontPagesPageid404 | |
| - | GetStorefrontPagesPageid500, | |
| - never | |
| ->; | |
| -type GetStorefrontPagesPageid = { | |
| - data: GetStorefrontPagesPageidQueryResponse; | |
| - error: | |
| - | GetStorefrontPagesPageid400 | |
| - | GetStorefrontPagesPageid401 | |
| - | GetStorefrontPagesPageid404 | |
| - | GetStorefrontPagesPageid500; | |
| - request: never; | |
| - pathParams: GetStorefrontPagesPageidPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStorefrontPagesPageidQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetStorefrontPagesPageidClient>[0]>; | |
| - return: Awaited<ReturnType<GetStorefrontPagesPageidClient>>; | |
| - }; | |
| -}; | |
| -export const getStorefrontPagesPageidQueryKey = ( | |
| - pageId: GetStorefrontPagesPageidPathParams["pageId"], | |
| -) => | |
| - [{ url: "/storefront-pages/:pageId", params: { pageId: pageId } }] as const; | |
| -export type GetStorefrontPagesPageidQueryKey = ReturnType< | |
| - typeof getStorefrontPagesPageidQueryKey | |
| ->; | |
| -export function getStorefrontPagesPageidQueryOptions( | |
| - pageId: GetStorefrontPagesPageidPathParams["pageId"], | |
| - options: GetStorefrontPagesPageid["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontPagesPageidQueryKey(pageId); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontPagesPageid["data"], | |
| - GetStorefrontPagesPageid["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefront-pages/${pageId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a specific storefront page by its ID | |
| - * @summary Get storefront page by ID | |
| - * @link /storefront-pages/:pageId | |
| - */ | |
| -export function useGetStorefrontPagesPageid< | |
| - TData = GetStorefrontPagesPageid["response"], | |
| - TQueryData = GetStorefrontPagesPageid["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontPagesPageidQueryKey, | |
| ->( | |
| - pageId: GetStorefrontPagesPageidPathParams["pageId"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontPagesPageid["response"], | |
| - GetStorefrontPagesPageid["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontPagesPageid["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontPagesPageid["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getStorefrontPagesPageidQueryKey(pageId); | |
| - const query = useQuery({ | |
| - ...(getStorefrontPagesPageidQueryOptions( | |
| - pageId, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetStorefrontPagesPageid["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontPagesPageidSuspenseQueryKey = ( | |
| - pageId: GetStorefrontPagesPageidPathParams["pageId"], | |
| -) => | |
| - [{ url: "/storefront-pages/:pageId", params: { pageId: pageId } }] as const; | |
| -export type GetStorefrontPagesPageidSuspenseQueryKey = ReturnType< | |
| - typeof getStorefrontPagesPageidSuspenseQueryKey | |
| ->; | |
| -export function getStorefrontPagesPageidSuspenseQueryOptions( | |
| - pageId: GetStorefrontPagesPageidPathParams["pageId"], | |
| - options: GetStorefrontPagesPageid["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontPagesPageidSuspenseQueryKey(pageId); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontPagesPageid["data"], | |
| - GetStorefrontPagesPageid["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefront-pages/${pageId}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a specific storefront page by its ID | |
| - * @summary Get storefront page by ID | |
| - * @link /storefront-pages/:pageId | |
| - */ | |
| -export function useGetStorefrontPagesPageidSuspense< | |
| - TData = GetStorefrontPagesPageid["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontPagesPageidSuspenseQueryKey, | |
| ->( | |
| - pageId: GetStorefrontPagesPageidPathParams["pageId"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontPagesPageid["response"], | |
| - GetStorefrontPagesPageid["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontPagesPageid["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetStorefrontPagesPageid["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getStorefrontPagesPageidSuspenseQueryKey(pageId); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontPagesPageidSuspenseQueryOptions( | |
| - pageId, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetStorefrontPagesPageid["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontsCustomDomainCustomDomain.ts b/src/phoenix-generated/hooks/useGetStorefrontsCustomDomainCustomDomain.ts | |
| deleted file mode 100644 | |
| index 483cea1c..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontsCustomDomainCustomDomain.ts | |
| +++ /dev/null | |
| @@ -1,205 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontsCustomDomainCustomDomain401, | |
| - GetStorefrontsCustomDomainCustomDomain404, | |
| - GetStorefrontsCustomDomainCustomDomain500, | |
| - GetStorefrontsCustomDomainCustomDomainPathParams, | |
| - GetStorefrontsCustomDomainCustomDomainQueryResponse, | |
| -} from "../types/GetStorefrontsCustomDomainCustomDomain"; | |
| - | |
| -type GetStorefrontsCustomDomainCustomDomainClient = typeof client< | |
| - GetStorefrontsCustomDomainCustomDomainQueryResponse, | |
| - | GetStorefrontsCustomDomainCustomDomain401 | |
| - | GetStorefrontsCustomDomainCustomDomain404 | |
| - | GetStorefrontsCustomDomainCustomDomain500, | |
| - never | |
| ->; | |
| -type GetStorefrontsCustomDomainCustomDomain = { | |
| - data: GetStorefrontsCustomDomainCustomDomainQueryResponse; | |
| - error: | |
| - | GetStorefrontsCustomDomainCustomDomain401 | |
| - | GetStorefrontsCustomDomainCustomDomain404 | |
| - | GetStorefrontsCustomDomainCustomDomain500; | |
| - request: never; | |
| - pathParams: GetStorefrontsCustomDomainCustomDomainPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStorefrontsCustomDomainCustomDomainQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetStorefrontsCustomDomainCustomDomainClient>[0] | |
| - >; | |
| - return: Awaited<ReturnType<GetStorefrontsCustomDomainCustomDomainClient>>; | |
| - }; | |
| -}; | |
| -export const getStorefrontsCustomDomainCustomDomainQueryKey = ( | |
| - customDomain: GetStorefrontsCustomDomainCustomDomainPathParams["custom_domain"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/custom-domain/:custom_domain", | |
| - params: { customDomain: customDomain }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsCustomDomainCustomDomainQueryKey = ReturnType< | |
| - typeof getStorefrontsCustomDomainCustomDomainQueryKey | |
| ->; | |
| -export function getStorefrontsCustomDomainCustomDomainQueryOptions( | |
| - customDomain: GetStorefrontsCustomDomainCustomDomainPathParams["custom_domain"], | |
| - options: GetStorefrontsCustomDomainCustomDomain["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsCustomDomainCustomDomainQueryKey(customDomain); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsCustomDomainCustomDomain["data"], | |
| - GetStorefrontsCustomDomainCustomDomain["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/custom-domain/${customDomain}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a storefront by its custom domain | |
| - * @summary Get storefront by custom domain | |
| - * @link /storefronts/custom-domain/:custom_domain | |
| - */ | |
| -export function useGetStorefrontsCustomDomainCustomDomain< | |
| - TData = GetStorefrontsCustomDomainCustomDomain["response"], | |
| - TQueryData = GetStorefrontsCustomDomainCustomDomain["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsCustomDomainCustomDomainQueryKey, | |
| ->( | |
| - customDomain: GetStorefrontsCustomDomainCustomDomainPathParams["custom_domain"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontsCustomDomainCustomDomain["response"], | |
| - GetStorefrontsCustomDomainCustomDomain["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsCustomDomainCustomDomain["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontsCustomDomainCustomDomain["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsCustomDomainCustomDomainQueryKey(customDomain); | |
| - const query = useQuery({ | |
| - ...(getStorefrontsCustomDomainCustomDomainQueryOptions( | |
| - customDomain, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult< | |
| - TData, | |
| - GetStorefrontsCustomDomainCustomDomain["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontsCustomDomainCustomDomainSuspenseQueryKey = ( | |
| - customDomain: GetStorefrontsCustomDomainCustomDomainPathParams["custom_domain"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/custom-domain/:custom_domain", | |
| - params: { customDomain: customDomain }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsCustomDomainCustomDomainSuspenseQueryKey = ReturnType< | |
| - typeof getStorefrontsCustomDomainCustomDomainSuspenseQueryKey | |
| ->; | |
| -export function getStorefrontsCustomDomainCustomDomainSuspenseQueryOptions( | |
| - customDomain: GetStorefrontsCustomDomainCustomDomainPathParams["custom_domain"], | |
| - options: GetStorefrontsCustomDomainCustomDomain["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getStorefrontsCustomDomainCustomDomainSuspenseQueryKey(customDomain); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsCustomDomainCustomDomain["data"], | |
| - GetStorefrontsCustomDomainCustomDomain["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/custom-domain/${customDomain}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a storefront by its custom domain | |
| - * @summary Get storefront by custom domain | |
| - * @link /storefronts/custom-domain/:custom_domain | |
| - */ | |
| -export function useGetStorefrontsCustomDomainCustomDomainSuspense< | |
| - TData = GetStorefrontsCustomDomainCustomDomain["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetStorefrontsCustomDomainCustomDomainSuspenseQueryKey, | |
| ->( | |
| - customDomain: GetStorefrontsCustomDomainCustomDomainPathParams["custom_domain"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontsCustomDomainCustomDomain["response"], | |
| - GetStorefrontsCustomDomainCustomDomain["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsCustomDomainCustomDomain["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsCustomDomainCustomDomain["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsCustomDomainCustomDomainSuspenseQueryKey(customDomain); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontsCustomDomainCustomDomainSuspenseQueryOptions( | |
| - customDomain, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsCustomDomainCustomDomain["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontsId.ts b/src/phoenix-generated/hooks/useGetStorefrontsId.ts | |
| deleted file mode 100644 | |
| index 1e2dd0db..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontsId.ts | |
| +++ /dev/null | |
| @@ -1,172 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontsId401, | |
| - GetStorefrontsId404, | |
| - GetStorefrontsId500, | |
| - GetStorefrontsIdPathParams, | |
| - GetStorefrontsIdQueryResponse, | |
| -} from "../types/GetStorefrontsId"; | |
| - | |
| -type GetStorefrontsIdClient = typeof client< | |
| - GetStorefrontsIdQueryResponse, | |
| - GetStorefrontsId401 | GetStorefrontsId404 | GetStorefrontsId500, | |
| - never | |
| ->; | |
| -type GetStorefrontsId = { | |
| - data: GetStorefrontsIdQueryResponse; | |
| - error: GetStorefrontsId401 | GetStorefrontsId404 | GetStorefrontsId500; | |
| - request: never; | |
| - pathParams: GetStorefrontsIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStorefrontsIdQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetStorefrontsIdClient>[0]>; | |
| - return: Awaited<ReturnType<GetStorefrontsIdClient>>; | |
| - }; | |
| -}; | |
| -export const getStorefrontsIdQueryKey = ( | |
| - id: GetStorefrontsIdPathParams["id"], | |
| -) => [{ url: "/storefronts/:id", params: { id: id } }] as const; | |
| -export type GetStorefrontsIdQueryKey = ReturnType< | |
| - typeof getStorefrontsIdQueryKey | |
| ->; | |
| -export function getStorefrontsIdQueryOptions( | |
| - id: GetStorefrontsIdPathParams["id"], | |
| - options: GetStorefrontsId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsIdQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsId["data"], | |
| - GetStorefrontsId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a storefront by its ID | |
| - * @summary Get storefront by ID | |
| - * @link /storefronts/:id | |
| - */ | |
| -export function useGetStorefrontsId< | |
| - TData = GetStorefrontsId["response"], | |
| - TQueryData = GetStorefrontsId["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsIdQueryKey, | |
| ->( | |
| - id: GetStorefrontsIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontsId["response"], | |
| - GetStorefrontsId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontsId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getStorefrontsIdQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getStorefrontsIdQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetStorefrontsId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontsIdSuspenseQueryKey = ( | |
| - id: GetStorefrontsIdPathParams["id"], | |
| -) => [{ url: "/storefronts/:id", params: { id: id } }] as const; | |
| -export type GetStorefrontsIdSuspenseQueryKey = ReturnType< | |
| - typeof getStorefrontsIdSuspenseQueryKey | |
| ->; | |
| -export function getStorefrontsIdSuspenseQueryOptions( | |
| - id: GetStorefrontsIdPathParams["id"], | |
| - options: GetStorefrontsId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsIdSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsId["data"], | |
| - GetStorefrontsId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a storefront by its ID | |
| - * @summary Get storefront by ID | |
| - * @link /storefronts/:id | |
| - */ | |
| -export function useGetStorefrontsIdSuspense< | |
| - TData = GetStorefrontsId["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsIdSuspenseQueryKey, | |
| ->( | |
| - id: GetStorefrontsIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontsId["response"], | |
| - GetStorefrontsId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetStorefrontsId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getStorefrontsIdSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontsIdSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetStorefrontsId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontsIdPages.ts b/src/phoenix-generated/hooks/useGetStorefrontsIdPages.ts | |
| deleted file mode 100644 | |
| index 0d07f630..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontsIdPages.ts | |
| +++ /dev/null | |
| @@ -1,200 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontsIdPages400, | |
| - GetStorefrontsIdPages401, | |
| - GetStorefrontsIdPages404, | |
| - GetStorefrontsIdPages500, | |
| - GetStorefrontsIdPagesPathParams, | |
| - GetStorefrontsIdPagesQueryParams, | |
| - GetStorefrontsIdPagesQueryResponse, | |
| -} from "../types/GetStorefrontsIdPages"; | |
| - | |
| -type GetStorefrontsIdPagesClient = typeof client< | |
| - GetStorefrontsIdPagesQueryResponse, | |
| - | GetStorefrontsIdPages400 | |
| - | GetStorefrontsIdPages401 | |
| - | GetStorefrontsIdPages404 | |
| - | GetStorefrontsIdPages500, | |
| - never | |
| ->; | |
| -type GetStorefrontsIdPages = { | |
| - data: GetStorefrontsIdPagesQueryResponse; | |
| - error: | |
| - | GetStorefrontsIdPages400 | |
| - | GetStorefrontsIdPages401 | |
| - | GetStorefrontsIdPages404 | |
| - | GetStorefrontsIdPages500; | |
| - request: never; | |
| - pathParams: GetStorefrontsIdPagesPathParams; | |
| - queryParams: GetStorefrontsIdPagesQueryParams; | |
| - headerParams: never; | |
| - response: GetStorefrontsIdPagesQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetStorefrontsIdPagesClient>[0]>; | |
| - return: Awaited<ReturnType<GetStorefrontsIdPagesClient>>; | |
| - }; | |
| -}; | |
| -export const getStorefrontsIdPagesQueryKey = ( | |
| - id: GetStorefrontsIdPagesPathParams["id"], | |
| - params?: GetStorefrontsIdPages["queryParams"], | |
| -) => | |
| - [ | |
| - { url: "/storefronts/:id/pages", params: { id: id } }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetStorefrontsIdPagesQueryKey = ReturnType< | |
| - typeof getStorefrontsIdPagesQueryKey | |
| ->; | |
| -export function getStorefrontsIdPagesQueryOptions( | |
| - id: GetStorefrontsIdPagesPathParams["id"], | |
| - params?: GetStorefrontsIdPages["queryParams"], | |
| - options: GetStorefrontsIdPages["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsIdPagesQueryKey(id, params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsIdPages["data"], | |
| - GetStorefrontsIdPages["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/${id}/pages`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List pages for a specific storefront | |
| - * @summary List storefront pages | |
| - * @link /storefronts/:id/pages | |
| - */ | |
| -export function useGetStorefrontsIdPages< | |
| - TData = GetStorefrontsIdPages["response"], | |
| - TQueryData = GetStorefrontsIdPages["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsIdPagesQueryKey, | |
| ->( | |
| - id: GetStorefrontsIdPagesPathParams["id"], | |
| - params?: GetStorefrontsIdPages["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontsIdPages["response"], | |
| - GetStorefrontsIdPages["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsIdPages["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontsIdPages["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getStorefrontsIdPagesQueryKey(id, params); | |
| - const query = useQuery({ | |
| - ...(getStorefrontsIdPagesQueryOptions( | |
| - id, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetStorefrontsIdPages["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontsIdPagesSuspenseQueryKey = ( | |
| - id: GetStorefrontsIdPagesPathParams["id"], | |
| - params?: GetStorefrontsIdPages["queryParams"], | |
| -) => | |
| - [ | |
| - { url: "/storefronts/:id/pages", params: { id: id } }, | |
| - ...(params ? [params] : []), | |
| - ] as const; | |
| -export type GetStorefrontsIdPagesSuspenseQueryKey = ReturnType< | |
| - typeof getStorefrontsIdPagesSuspenseQueryKey | |
| ->; | |
| -export function getStorefrontsIdPagesSuspenseQueryOptions( | |
| - id: GetStorefrontsIdPagesPathParams["id"], | |
| - params?: GetStorefrontsIdPages["queryParams"], | |
| - options: GetStorefrontsIdPages["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsIdPagesSuspenseQueryKey(id, params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsIdPages["data"], | |
| - GetStorefrontsIdPages["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/${id}/pages`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List pages for a specific storefront | |
| - * @summary List storefront pages | |
| - * @link /storefronts/:id/pages | |
| - */ | |
| -export function useGetStorefrontsIdPagesSuspense< | |
| - TData = GetStorefrontsIdPages["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsIdPagesSuspenseQueryKey, | |
| ->( | |
| - id: GetStorefrontsIdPagesPathParams["id"], | |
| - params?: GetStorefrontsIdPages["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontsIdPages["response"], | |
| - GetStorefrontsIdPages["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsIdPages["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetStorefrontsIdPages["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getStorefrontsIdPagesSuspenseQueryKey(id, params); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontsIdPagesSuspenseQueryOptions( | |
| - id, | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetStorefrontsIdPages["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomain.ts b/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomain.ts | |
| deleted file mode 100644 | |
| index 7343d1c3..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomain.ts | |
| +++ /dev/null | |
| @@ -1,195 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontsSubdomainSubdomain401, | |
| - GetStorefrontsSubdomainSubdomain404, | |
| - GetStorefrontsSubdomainSubdomain500, | |
| - GetStorefrontsSubdomainSubdomainPathParams, | |
| - GetStorefrontsSubdomainSubdomainQueryResponse, | |
| -} from "../types/GetStorefrontsSubdomainSubdomain"; | |
| - | |
| -type GetStorefrontsSubdomainSubdomainClient = typeof client< | |
| - GetStorefrontsSubdomainSubdomainQueryResponse, | |
| - | GetStorefrontsSubdomainSubdomain401 | |
| - | GetStorefrontsSubdomainSubdomain404 | |
| - | GetStorefrontsSubdomainSubdomain500, | |
| - never | |
| ->; | |
| -type GetStorefrontsSubdomainSubdomain = { | |
| - data: GetStorefrontsSubdomainSubdomainQueryResponse; | |
| - error: | |
| - | GetStorefrontsSubdomainSubdomain401 | |
| - | GetStorefrontsSubdomainSubdomain404 | |
| - | GetStorefrontsSubdomainSubdomain500; | |
| - request: never; | |
| - pathParams: GetStorefrontsSubdomainSubdomainPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStorefrontsSubdomainSubdomainQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetStorefrontsSubdomainSubdomainClient>[0]>; | |
| - return: Awaited<ReturnType<GetStorefrontsSubdomainSubdomainClient>>; | |
| - }; | |
| -}; | |
| -export const getStorefrontsSubdomainSubdomainQueryKey = ( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPathParams["subdomain"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/subdomain/:subdomain", | |
| - params: { subdomain: subdomain }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsSubdomainSubdomainQueryKey = ReturnType< | |
| - typeof getStorefrontsSubdomainSubdomainQueryKey | |
| ->; | |
| -export function getStorefrontsSubdomainSubdomainQueryOptions( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPathParams["subdomain"], | |
| - options: GetStorefrontsSubdomainSubdomain["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsSubdomainSubdomainQueryKey(subdomain); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsSubdomainSubdomain["data"], | |
| - GetStorefrontsSubdomainSubdomain["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/subdomain/${subdomain}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a storefront by its subdomain | |
| - * @summary Get storefront by subdomain | |
| - * @link /storefronts/subdomain/:subdomain | |
| - */ | |
| -export function useGetStorefrontsSubdomainSubdomain< | |
| - TData = GetStorefrontsSubdomainSubdomain["response"], | |
| - TQueryData = GetStorefrontsSubdomainSubdomain["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsSubdomainSubdomainQueryKey, | |
| ->( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPathParams["subdomain"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontsSubdomainSubdomain["response"], | |
| - GetStorefrontsSubdomainSubdomain["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsSubdomainSubdomain["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontsSubdomainSubdomain["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsSubdomainSubdomainQueryKey(subdomain); | |
| - const query = useQuery({ | |
| - ...(getStorefrontsSubdomainSubdomainQueryOptions( | |
| - subdomain, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetStorefrontsSubdomainSubdomain["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontsSubdomainSubdomainSuspenseQueryKey = ( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPathParams["subdomain"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/subdomain/:subdomain", | |
| - params: { subdomain: subdomain }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsSubdomainSubdomainSuspenseQueryKey = ReturnType< | |
| - typeof getStorefrontsSubdomainSubdomainSuspenseQueryKey | |
| ->; | |
| -export function getStorefrontsSubdomainSubdomainSuspenseQueryOptions( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPathParams["subdomain"], | |
| - options: GetStorefrontsSubdomainSubdomain["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsSubdomainSubdomainSuspenseQueryKey(subdomain); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsSubdomainSubdomain["data"], | |
| - GetStorefrontsSubdomainSubdomain["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/subdomain/${subdomain}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a storefront by its subdomain | |
| - * @summary Get storefront by subdomain | |
| - * @link /storefronts/subdomain/:subdomain | |
| - */ | |
| -export function useGetStorefrontsSubdomainSubdomainSuspense< | |
| - TData = GetStorefrontsSubdomainSubdomain["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsSubdomainSubdomainSuspenseQueryKey, | |
| ->( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPathParams["subdomain"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontsSubdomainSubdomain["response"], | |
| - GetStorefrontsSubdomainSubdomain["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsSubdomainSubdomain["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetStorefrontsSubdomainSubdomain["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsSubdomainSubdomainSuspenseQueryKey(subdomain); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontsSubdomainSubdomainSuspenseQueryOptions( | |
| - subdomain, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomain["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomainCheck.ts b/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomainCheck.ts | |
| deleted file mode 100644 | |
| index 3d27ebbe..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomainCheck.ts | |
| +++ /dev/null | |
| @@ -1,202 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontsSubdomainSubdomainCheck400, | |
| - GetStorefrontsSubdomainSubdomainCheck500, | |
| - GetStorefrontsSubdomainSubdomainCheckPathParams, | |
| - GetStorefrontsSubdomainSubdomainCheckQueryResponse, | |
| -} from "../types/GetStorefrontsSubdomainSubdomainCheck"; | |
| - | |
| -type GetStorefrontsSubdomainSubdomainCheckClient = typeof client< | |
| - GetStorefrontsSubdomainSubdomainCheckQueryResponse, | |
| - | GetStorefrontsSubdomainSubdomainCheck400 | |
| - | GetStorefrontsSubdomainSubdomainCheck500, | |
| - never | |
| ->; | |
| -type GetStorefrontsSubdomainSubdomainCheck = { | |
| - data: GetStorefrontsSubdomainSubdomainCheckQueryResponse; | |
| - error: | |
| - | GetStorefrontsSubdomainSubdomainCheck400 | |
| - | GetStorefrontsSubdomainSubdomainCheck500; | |
| - request: never; | |
| - pathParams: GetStorefrontsSubdomainSubdomainCheckPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStorefrontsSubdomainSubdomainCheckQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetStorefrontsSubdomainSubdomainCheckClient>[0] | |
| - >; | |
| - return: Awaited<ReturnType<GetStorefrontsSubdomainSubdomainCheckClient>>; | |
| - }; | |
| -}; | |
| -export const getStorefrontsSubdomainSubdomainCheckQueryKey = ( | |
| - subdomain: GetStorefrontsSubdomainSubdomainCheckPathParams["subdomain"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/subdomain/:subdomain/check", | |
| - params: { subdomain: subdomain }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsSubdomainSubdomainCheckQueryKey = ReturnType< | |
| - typeof getStorefrontsSubdomainSubdomainCheckQueryKey | |
| ->; | |
| -export function getStorefrontsSubdomainSubdomainCheckQueryOptions( | |
| - subdomain: GetStorefrontsSubdomainSubdomainCheckPathParams["subdomain"], | |
| - options: GetStorefrontsSubdomainSubdomainCheck["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsSubdomainSubdomainCheckQueryKey(subdomain); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsSubdomainSubdomainCheck["data"], | |
| - GetStorefrontsSubdomainSubdomainCheck["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/subdomain/${subdomain}/check`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Check if a subdomain is available for use | |
| - * @summary Check subdomain availability | |
| - * @link /storefronts/subdomain/:subdomain/check | |
| - */ | |
| -export function useGetStorefrontsSubdomainSubdomainCheck< | |
| - TData = GetStorefrontsSubdomainSubdomainCheck["response"], | |
| - TQueryData = GetStorefrontsSubdomainSubdomainCheck["response"], | |
| - TQueryKey extends QueryKey = GetStorefrontsSubdomainSubdomainCheckQueryKey, | |
| ->( | |
| - subdomain: GetStorefrontsSubdomainSubdomainCheckPathParams["subdomain"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontsSubdomainSubdomainCheck["response"], | |
| - GetStorefrontsSubdomainSubdomainCheck["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsSubdomainSubdomainCheck["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontsSubdomainSubdomainCheck["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsSubdomainSubdomainCheckQueryKey(subdomain); | |
| - const query = useQuery({ | |
| - ...(getStorefrontsSubdomainSubdomainCheckQueryOptions( | |
| - subdomain, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomainCheck["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontsSubdomainSubdomainCheckSuspenseQueryKey = ( | |
| - subdomain: GetStorefrontsSubdomainSubdomainCheckPathParams["subdomain"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/subdomain/:subdomain/check", | |
| - params: { subdomain: subdomain }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsSubdomainSubdomainCheckSuspenseQueryKey = ReturnType< | |
| - typeof getStorefrontsSubdomainSubdomainCheckSuspenseQueryKey | |
| ->; | |
| -export function getStorefrontsSubdomainSubdomainCheckSuspenseQueryOptions( | |
| - subdomain: GetStorefrontsSubdomainSubdomainCheckPathParams["subdomain"], | |
| - options: GetStorefrontsSubdomainSubdomainCheck["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = | |
| - getStorefrontsSubdomainSubdomainCheckSuspenseQueryKey(subdomain); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsSubdomainSubdomainCheck["data"], | |
| - GetStorefrontsSubdomainSubdomainCheck["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/subdomain/${subdomain}/check`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Check if a subdomain is available for use | |
| - * @summary Check subdomain availability | |
| - * @link /storefronts/subdomain/:subdomain/check | |
| - */ | |
| -export function useGetStorefrontsSubdomainSubdomainCheckSuspense< | |
| - TData = GetStorefrontsSubdomainSubdomainCheck["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetStorefrontsSubdomainSubdomainCheckSuspenseQueryKey, | |
| ->( | |
| - subdomain: GetStorefrontsSubdomainSubdomainCheckPathParams["subdomain"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontsSubdomainSubdomainCheck["response"], | |
| - GetStorefrontsSubdomainSubdomainCheck["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsSubdomainSubdomainCheck["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomainCheck["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsSubdomainSubdomainCheckSuspenseQueryKey(subdomain); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontsSubdomainSubdomainCheckSuspenseQueryOptions( | |
| - subdomain, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomainCheck["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomainPagesPath.ts b/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomainPagesPath.ts | |
| deleted file mode 100644 | |
| index 17bcf881..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetStorefrontsSubdomainSubdomainPagesPath.ts | |
| +++ /dev/null | |
| @@ -1,220 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetStorefrontsSubdomainSubdomainPagesPath400, | |
| - GetStorefrontsSubdomainSubdomainPagesPath404, | |
| - GetStorefrontsSubdomainSubdomainPagesPath500, | |
| - GetStorefrontsSubdomainSubdomainPagesPathPathParams, | |
| - GetStorefrontsSubdomainSubdomainPagesPathQueryResponse, | |
| -} from "../types/GetStorefrontsSubdomainSubdomainPagesPath"; | |
| - | |
| -type GetStorefrontsSubdomainSubdomainPagesPathClient = typeof client< | |
| - GetStorefrontsSubdomainSubdomainPagesPathQueryResponse, | |
| - | GetStorefrontsSubdomainSubdomainPagesPath400 | |
| - | GetStorefrontsSubdomainSubdomainPagesPath404 | |
| - | GetStorefrontsSubdomainSubdomainPagesPath500, | |
| - never | |
| ->; | |
| -type GetStorefrontsSubdomainSubdomainPagesPath = { | |
| - data: GetStorefrontsSubdomainSubdomainPagesPathQueryResponse; | |
| - error: | |
| - | GetStorefrontsSubdomainSubdomainPagesPath400 | |
| - | GetStorefrontsSubdomainSubdomainPagesPath404 | |
| - | GetStorefrontsSubdomainSubdomainPagesPath500; | |
| - request: never; | |
| - pathParams: GetStorefrontsSubdomainSubdomainPagesPathPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetStorefrontsSubdomainSubdomainPagesPathQueryResponse; | |
| - client: { | |
| - parameters: Partial< | |
| - Parameters<GetStorefrontsSubdomainSubdomainPagesPathClient>[0] | |
| - >; | |
| - return: Awaited< | |
| - ReturnType<GetStorefrontsSubdomainSubdomainPagesPathClient> | |
| - >; | |
| - }; | |
| -}; | |
| -export const getStorefrontsSubdomainSubdomainPagesPathQueryKey = ( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPagesPathPathParams["subdomain"], | |
| - path: GetStorefrontsSubdomainSubdomainPagesPathPathParams["path"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/subdomain/:subdomain/pages/:path", | |
| - params: { subdomain: subdomain, path: path }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsSubdomainSubdomainPagesPathQueryKey = ReturnType< | |
| - typeof getStorefrontsSubdomainSubdomainPagesPathQueryKey | |
| ->; | |
| -export function getStorefrontsSubdomainSubdomainPagesPathQueryOptions( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPagesPathPathParams["subdomain"], | |
| - path: GetStorefrontsSubdomainSubdomainPagesPathPathParams["path"], | |
| - options: GetStorefrontsSubdomainSubdomainPagesPath["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsSubdomainSubdomainPagesPathQueryKey( | |
| - subdomain, | |
| - path, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsSubdomainSubdomainPagesPath["data"], | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/subdomain/${subdomain}/pages/${path}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a specific page by storefront subdomain and page path | |
| - * @summary Get storefront page by subdomain and path | |
| - * @link /storefronts/subdomain/:subdomain/pages/:path | |
| - */ | |
| -export function useGetStorefrontsSubdomainSubdomainPagesPath< | |
| - TData = GetStorefrontsSubdomainSubdomainPagesPath["response"], | |
| - TQueryData = GetStorefrontsSubdomainSubdomainPagesPath["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetStorefrontsSubdomainSubdomainPagesPathQueryKey, | |
| ->( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPagesPathPathParams["subdomain"], | |
| - path: GetStorefrontsSubdomainSubdomainPagesPathPathParams["path"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetStorefrontsSubdomainSubdomainPagesPath["response"], | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsSubdomainSubdomainPagesPath["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetStorefrontsSubdomainSubdomainPagesPath["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsSubdomainSubdomainPagesPathQueryKey(subdomain, path); | |
| - const query = useQuery({ | |
| - ...(getStorefrontsSubdomainSubdomainPagesPathQueryOptions( | |
| - subdomain, | |
| - path, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getStorefrontsSubdomainSubdomainPagesPathSuspenseQueryKey = ( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPagesPathPathParams["subdomain"], | |
| - path: GetStorefrontsSubdomainSubdomainPagesPathPathParams["path"], | |
| -) => | |
| - [ | |
| - { | |
| - url: "/storefronts/subdomain/:subdomain/pages/:path", | |
| - params: { subdomain: subdomain, path: path }, | |
| - }, | |
| - ] as const; | |
| -export type GetStorefrontsSubdomainSubdomainPagesPathSuspenseQueryKey = | |
| - ReturnType<typeof getStorefrontsSubdomainSubdomainPagesPathSuspenseQueryKey>; | |
| -export function getStorefrontsSubdomainSubdomainPagesPathSuspenseQueryOptions( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPagesPathPathParams["subdomain"], | |
| - path: GetStorefrontsSubdomainSubdomainPagesPathPathParams["path"], | |
| - options: GetStorefrontsSubdomainSubdomainPagesPath["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getStorefrontsSubdomainSubdomainPagesPathSuspenseQueryKey( | |
| - subdomain, | |
| - path, | |
| - ); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetStorefrontsSubdomainSubdomainPagesPath["data"], | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts/subdomain/${subdomain}/pages/${path}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get a specific page by storefront subdomain and page path | |
| - * @summary Get storefront page by subdomain and path | |
| - * @link /storefronts/subdomain/:subdomain/pages/:path | |
| - */ | |
| -export function useGetStorefrontsSubdomainSubdomainPagesPathSuspense< | |
| - TData = GetStorefrontsSubdomainSubdomainPagesPath["response"], | |
| - TQueryKey extends | |
| - QueryKey = GetStorefrontsSubdomainSubdomainPagesPathSuspenseQueryKey, | |
| ->( | |
| - subdomain: GetStorefrontsSubdomainSubdomainPagesPathPathParams["subdomain"], | |
| - path: GetStorefrontsSubdomainSubdomainPagesPathPathParams["path"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetStorefrontsSubdomainSubdomainPagesPath["response"], | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetStorefrontsSubdomainSubdomainPagesPath["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"] | |
| -> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getStorefrontsSubdomainSubdomainPagesPathSuspenseQueryKey(subdomain, path); | |
| - const query = useSuspenseQuery({ | |
| - ...(getStorefrontsSubdomainSubdomainPagesPathSuspenseQueryOptions( | |
| - subdomain, | |
| - path, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetStorefrontsSubdomainSubdomainPagesPath["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetTransactionByTransactionItem.ts b/src/phoenix-generated/hooks/useGetTransactionByTransactionItem.ts | |
| deleted file mode 100644 | |
| index a463bb25..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetTransactionByTransactionItem.ts | |
| +++ /dev/null | |
| @@ -1,187 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetTransactionByTransactionItem400, | |
| - GetTransactionByTransactionItem401, | |
| - GetTransactionByTransactionItem404, | |
| - GetTransactionByTransactionItem500, | |
| - GetTransactionByTransactionItemPathParams, | |
| - GetTransactionByTransactionItemQueryResponse, | |
| -} from "../types/GetTransactionByTransactionItem"; | |
| - | |
| -type GetTransactionByTransactionItemClient = typeof client< | |
| - GetTransactionByTransactionItemQueryResponse, | |
| - | GetTransactionByTransactionItem400 | |
| - | GetTransactionByTransactionItem401 | |
| - | GetTransactionByTransactionItem404 | |
| - | GetTransactionByTransactionItem500, | |
| - never | |
| ->; | |
| -type GetTransactionByTransactionItem = { | |
| - data: GetTransactionByTransactionItemQueryResponse; | |
| - error: | |
| - | GetTransactionByTransactionItem400 | |
| - | GetTransactionByTransactionItem401 | |
| - | GetTransactionByTransactionItem404 | |
| - | GetTransactionByTransactionItem500; | |
| - request: never; | |
| - pathParams: GetTransactionByTransactionItemPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetTransactionByTransactionItemQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetTransactionByTransactionItemClient>[0]>; | |
| - return: Awaited<ReturnType<GetTransactionByTransactionItemClient>>; | |
| - }; | |
| -}; | |
| -export const getTransactionByTransactionItemQueryKey = ( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| -) => | |
| - [{ url: "/transaction/transaction-item/:id", params: { id: id } }] as const; | |
| -export type GetTransactionByTransactionItemQueryKey = ReturnType< | |
| - typeof getTransactionByTransactionItemQueryKey | |
| ->; | |
| -export function getTransactionByTransactionItemQueryOptions( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| - options: GetTransactionByTransactionItem["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getTransactionByTransactionItemQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetTransactionByTransactionItem["data"], | |
| - GetTransactionByTransactionItem["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction/transaction-item/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get transaction by transaction item ID | |
| - * @summary Get transaction by transaction item | |
| - * @link /transaction/transaction-item/:id | |
| - */ | |
| -export function useGetTransactionByTransactionItem< | |
| - TData = GetTransactionByTransactionItem["response"], | |
| - TQueryData = GetTransactionByTransactionItem["response"], | |
| - TQueryKey extends QueryKey = GetTransactionByTransactionItemQueryKey, | |
| ->( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetTransactionByTransactionItem["response"], | |
| - GetTransactionByTransactionItem["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetTransactionByTransactionItem["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetTransactionByTransactionItem["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getTransactionByTransactionItemQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getTransactionByTransactionItemQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetTransactionByTransactionItem["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getTransactionByTransactionItemSuspenseQueryKey = ( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| -) => | |
| - [{ url: "/transaction/transaction-item/:id", params: { id: id } }] as const; | |
| -export type GetTransactionByTransactionItemSuspenseQueryKey = ReturnType< | |
| - typeof getTransactionByTransactionItemSuspenseQueryKey | |
| ->; | |
| -export function getTransactionByTransactionItemSuspenseQueryOptions( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| - options: GetTransactionByTransactionItem["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getTransactionByTransactionItemSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetTransactionByTransactionItem["data"], | |
| - GetTransactionByTransactionItem["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction/transaction-item/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get transaction by transaction item ID | |
| - * @summary Get transaction by transaction item | |
| - * @link /transaction/transaction-item/:id | |
| - */ | |
| -export function useGetTransactionByTransactionItemSuspense< | |
| - TData = GetTransactionByTransactionItem["response"], | |
| - TQueryKey extends QueryKey = GetTransactionByTransactionItemSuspenseQueryKey, | |
| ->( | |
| - id: GetTransactionByTransactionItemPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetTransactionByTransactionItem["response"], | |
| - GetTransactionByTransactionItem["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetTransactionByTransactionItem["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetTransactionByTransactionItem["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? | |
| - getTransactionByTransactionItemSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getTransactionByTransactionItemSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult< | |
| - TData, | |
| - GetTransactionByTransactionItem["error"] | |
| - > & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetTransactionId.ts b/src/phoenix-generated/hooks/useGetTransactionId.ts | |
| deleted file mode 100644 | |
| index 99631f1b..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetTransactionId.ts | |
| +++ /dev/null | |
| @@ -1,180 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetTransactionId400, | |
| - GetTransactionId401, | |
| - GetTransactionId404, | |
| - GetTransactionId500, | |
| - GetTransactionIdPathParams, | |
| - GetTransactionIdQueryResponse, | |
| -} from "../types/GetTransactionId"; | |
| - | |
| -type GetTransactionIdClient = typeof client< | |
| - GetTransactionIdQueryResponse, | |
| - | GetTransactionId400 | |
| - | GetTransactionId401 | |
| - | GetTransactionId404 | |
| - | GetTransactionId500, | |
| - never | |
| ->; | |
| -type GetTransactionId = { | |
| - data: GetTransactionIdQueryResponse; | |
| - error: | |
| - | GetTransactionId400 | |
| - | GetTransactionId401 | |
| - | GetTransactionId404 | |
| - | GetTransactionId500; | |
| - request: never; | |
| - pathParams: GetTransactionIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetTransactionIdQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetTransactionIdClient>[0]>; | |
| - return: Awaited<ReturnType<GetTransactionIdClient>>; | |
| - }; | |
| -}; | |
| -export const getTransactionIdQueryKey = ( | |
| - id: GetTransactionIdPathParams["id"], | |
| -) => [{ url: "/transaction/:id", params: { id: id } }] as const; | |
| -export type GetTransactionIdQueryKey = ReturnType< | |
| - typeof getTransactionIdQueryKey | |
| ->; | |
| -export function getTransactionIdQueryOptions( | |
| - id: GetTransactionIdPathParams["id"], | |
| - options: GetTransactionId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getTransactionIdQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetTransactionId["data"], | |
| - GetTransactionId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get transaction by ID | |
| - * @summary Get transaction | |
| - * @link /transaction/:id | |
| - */ | |
| -export function useGetTransactionId< | |
| - TData = GetTransactionId["response"], | |
| - TQueryData = GetTransactionId["response"], | |
| - TQueryKey extends QueryKey = GetTransactionIdQueryKey, | |
| ->( | |
| - id: GetTransactionIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetTransactionId["response"], | |
| - GetTransactionId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetTransactionId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetTransactionId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getTransactionIdQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getTransactionIdQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetTransactionId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getTransactionIdSuspenseQueryKey = ( | |
| - id: GetTransactionIdPathParams["id"], | |
| -) => [{ url: "/transaction/:id", params: { id: id } }] as const; | |
| -export type GetTransactionIdSuspenseQueryKey = ReturnType< | |
| - typeof getTransactionIdSuspenseQueryKey | |
| ->; | |
| -export function getTransactionIdSuspenseQueryOptions( | |
| - id: GetTransactionIdPathParams["id"], | |
| - options: GetTransactionId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getTransactionIdSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetTransactionId["data"], | |
| - GetTransactionId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get transaction by ID | |
| - * @summary Get transaction | |
| - * @link /transaction/:id | |
| - */ | |
| -export function useGetTransactionIdSuspense< | |
| - TData = GetTransactionId["response"], | |
| - TQueryKey extends QueryKey = GetTransactionIdSuspenseQueryKey, | |
| ->( | |
| - id: GetTransactionIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetTransactionId["response"], | |
| - GetTransactionId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetTransactionId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetTransactionId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getTransactionIdSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getTransactionIdSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetTransactionId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetTransactionItemId.ts b/src/phoenix-generated/hooks/useGetTransactionItemId.ts | |
| deleted file mode 100644 | |
| index 4afb90e4..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetTransactionItemId.ts | |
| +++ /dev/null | |
| @@ -1,180 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetTransactionItemId400, | |
| - GetTransactionItemId401, | |
| - GetTransactionItemId404, | |
| - GetTransactionItemId500, | |
| - GetTransactionItemIdPathParams, | |
| - GetTransactionItemIdQueryResponse, | |
| -} from "../types/GetTransactionItemId"; | |
| - | |
| -type GetTransactionItemIdClient = typeof client< | |
| - GetTransactionItemIdQueryResponse, | |
| - | GetTransactionItemId400 | |
| - | GetTransactionItemId401 | |
| - | GetTransactionItemId404 | |
| - | GetTransactionItemId500, | |
| - never | |
| ->; | |
| -type GetTransactionItemId = { | |
| - data: GetTransactionItemIdQueryResponse; | |
| - error: | |
| - | GetTransactionItemId400 | |
| - | GetTransactionItemId401 | |
| - | GetTransactionItemId404 | |
| - | GetTransactionItemId500; | |
| - request: never; | |
| - pathParams: GetTransactionItemIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetTransactionItemIdQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetTransactionItemIdClient>[0]>; | |
| - return: Awaited<ReturnType<GetTransactionItemIdClient>>; | |
| - }; | |
| -}; | |
| -export const getTransactionItemIdQueryKey = ( | |
| - id: GetTransactionItemIdPathParams["id"], | |
| -) => [{ url: "/transaction-item/:id", params: { id: id } }] as const; | |
| -export type GetTransactionItemIdQueryKey = ReturnType< | |
| - typeof getTransactionItemIdQueryKey | |
| ->; | |
| -export function getTransactionItemIdQueryOptions( | |
| - id: GetTransactionItemIdPathParams["id"], | |
| - options: GetTransactionItemId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getTransactionItemIdQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetTransactionItemId["data"], | |
| - GetTransactionItemId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction-item/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get transaction item by ID | |
| - * @summary Get transaction item | |
| - * @link /transaction-item/:id | |
| - */ | |
| -export function useGetTransactionItemId< | |
| - TData = GetTransactionItemId["response"], | |
| - TQueryData = GetTransactionItemId["response"], | |
| - TQueryKey extends QueryKey = GetTransactionItemIdQueryKey, | |
| ->( | |
| - id: GetTransactionItemIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetTransactionItemId["response"], | |
| - GetTransactionItemId["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetTransactionItemId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetTransactionItemId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getTransactionItemIdQueryKey(id); | |
| - const query = useQuery({ | |
| - ...(getTransactionItemIdQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetTransactionItemId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getTransactionItemIdSuspenseQueryKey = ( | |
| - id: GetTransactionItemIdPathParams["id"], | |
| -) => [{ url: "/transaction-item/:id", params: { id: id } }] as const; | |
| -export type GetTransactionItemIdSuspenseQueryKey = ReturnType< | |
| - typeof getTransactionItemIdSuspenseQueryKey | |
| ->; | |
| -export function getTransactionItemIdSuspenseQueryOptions( | |
| - id: GetTransactionItemIdPathParams["id"], | |
| - options: GetTransactionItemId["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getTransactionItemIdSuspenseQueryKey(id); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetTransactionItemId["data"], | |
| - GetTransactionItemId["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction-item/${id}`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get transaction item by ID | |
| - * @summary Get transaction item | |
| - * @link /transaction-item/:id | |
| - */ | |
| -export function useGetTransactionItemIdSuspense< | |
| - TData = GetTransactionItemId["response"], | |
| - TQueryKey extends QueryKey = GetTransactionItemIdSuspenseQueryKey, | |
| ->( | |
| - id: GetTransactionItemIdPathParams["id"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetTransactionItemId["response"], | |
| - GetTransactionItemId["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetTransactionItemId["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetTransactionItemId["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getTransactionItemIdSuspenseQueryKey(id); | |
| - const query = useSuspenseQuery({ | |
| - ...(getTransactionItemIdSuspenseQueryOptions( | |
| - id, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetTransactionItemId["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetWebsocketConnections.ts b/src/phoenix-generated/hooks/useGetWebsocketConnections.ts | |
| deleted file mode 100644 | |
| index fd2bcdb3..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetWebsocketConnections.ts | |
| +++ /dev/null | |
| @@ -1,180 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetWebsocketConnections400, | |
| - GetWebsocketConnections401, | |
| - GetWebsocketConnections500, | |
| - GetWebsocketConnectionsQueryParams, | |
| - GetWebsocketConnectionsQueryResponse, | |
| -} from "../types/GetWebsocketConnections"; | |
| - | |
| -type GetWebsocketConnectionsClient = typeof client< | |
| - GetWebsocketConnectionsQueryResponse, | |
| - | GetWebsocketConnections400 | |
| - | GetWebsocketConnections401 | |
| - | GetWebsocketConnections500, | |
| - never | |
| ->; | |
| -type GetWebsocketConnections = { | |
| - data: GetWebsocketConnectionsQueryResponse; | |
| - error: | |
| - | GetWebsocketConnections400 | |
| - | GetWebsocketConnections401 | |
| - | GetWebsocketConnections500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: GetWebsocketConnectionsQueryParams; | |
| - headerParams: never; | |
| - response: GetWebsocketConnectionsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetWebsocketConnectionsClient>[0]>; | |
| - return: Awaited<ReturnType<GetWebsocketConnectionsClient>>; | |
| - }; | |
| -}; | |
| -export const getWebsocketConnectionsQueryKey = ( | |
| - params: GetWebsocketConnections["queryParams"], | |
| -) => [{ url: "/websocket/connection" }, ...(params ? [params] : [])] as const; | |
| -export type GetWebsocketConnectionsQueryKey = ReturnType< | |
| - typeof getWebsocketConnectionsQueryKey | |
| ->; | |
| -export function getWebsocketConnectionsQueryOptions( | |
| - params: GetWebsocketConnections["queryParams"], | |
| - options: GetWebsocketConnections["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getWebsocketConnectionsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetWebsocketConnections["data"], | |
| - GetWebsocketConnections["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/websocket/connection`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get websocket connections | |
| - * @summary Get websocket connections | |
| - * @link /websocket/connection | |
| - */ | |
| -export function useGetWebsocketConnections< | |
| - TData = GetWebsocketConnections["response"], | |
| - TQueryData = GetWebsocketConnections["response"], | |
| - TQueryKey extends QueryKey = GetWebsocketConnectionsQueryKey, | |
| ->( | |
| - params: GetWebsocketConnections["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetWebsocketConnections["response"], | |
| - GetWebsocketConnections["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetWebsocketConnections["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetWebsocketConnections["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getWebsocketConnectionsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(getWebsocketConnectionsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetWebsocketConnections["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getWebsocketConnectionsSuspenseQueryKey = ( | |
| - params: GetWebsocketConnections["queryParams"], | |
| -) => [{ url: "/websocket/connection" }, ...(params ? [params] : [])] as const; | |
| -export type GetWebsocketConnectionsSuspenseQueryKey = ReturnType< | |
| - typeof getWebsocketConnectionsSuspenseQueryKey | |
| ->; | |
| -export function getWebsocketConnectionsSuspenseQueryOptions( | |
| - params: GetWebsocketConnections["queryParams"], | |
| - options: GetWebsocketConnections["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getWebsocketConnectionsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetWebsocketConnections["data"], | |
| - GetWebsocketConnections["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/websocket/connection`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get websocket connections | |
| - * @summary Get websocket connections | |
| - * @link /websocket/connection | |
| - */ | |
| -export function useGetWebsocketConnectionsSuspense< | |
| - TData = GetWebsocketConnections["response"], | |
| - TQueryKey extends QueryKey = GetWebsocketConnectionsSuspenseQueryKey, | |
| ->( | |
| - params: GetWebsocketConnections["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetWebsocketConnections["response"], | |
| - GetWebsocketConnections["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetWebsocketConnections["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetWebsocketConnections["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getWebsocketConnectionsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(getWebsocketConnectionsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetWebsocketConnections["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useGetWebsocketMessage.ts b/src/phoenix-generated/hooks/useGetWebsocketMessage.ts | |
| deleted file mode 100644 | |
| index 705a1de0..00000000 | |
| --- a/src/phoenix-generated/hooks/useGetWebsocketMessage.ts | |
| +++ /dev/null | |
| @@ -1,171 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - GetWebsocketMessage400, | |
| - GetWebsocketMessage401, | |
| - GetWebsocketMessage404, | |
| - GetWebsocketMessage500, | |
| - GetWebsocketMessageQueryResponse, | |
| -} from "../types/GetWebsocketMessage"; | |
| - | |
| -type GetWebsocketMessageClient = typeof client< | |
| - GetWebsocketMessageQueryResponse, | |
| - | GetWebsocketMessage400 | |
| - | GetWebsocketMessage401 | |
| - | GetWebsocketMessage404 | |
| - | GetWebsocketMessage500, | |
| - never | |
| ->; | |
| -type GetWebsocketMessage = { | |
| - data: GetWebsocketMessageQueryResponse; | |
| - error: | |
| - | GetWebsocketMessage400 | |
| - | GetWebsocketMessage401 | |
| - | GetWebsocketMessage404 | |
| - | GetWebsocketMessage500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: GetWebsocketMessageQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<GetWebsocketMessageClient>[0]>; | |
| - return: Awaited<ReturnType<GetWebsocketMessageClient>>; | |
| - }; | |
| -}; | |
| -export const getWebsocketMessageQueryKey = () => | |
| - [{ url: "/websocket/message" }] as const; | |
| -export type GetWebsocketMessageQueryKey = ReturnType< | |
| - typeof getWebsocketMessageQueryKey | |
| ->; | |
| -export function getWebsocketMessageQueryOptions( | |
| - options: GetWebsocketMessage["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getWebsocketMessageQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetWebsocketMessage["data"], | |
| - GetWebsocketMessage["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/websocket/message`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get websocket message | |
| - * @summary Get websocket message (This isn't implemented yet, emitted for swagger type) | |
| - * @link /websocket/message | |
| - */ | |
| -export function useGetWebsocketMessage< | |
| - TData = GetWebsocketMessage["response"], | |
| - TQueryData = GetWebsocketMessage["response"], | |
| - TQueryKey extends QueryKey = GetWebsocketMessageQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - GetWebsocketMessage["response"], | |
| - GetWebsocketMessage["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetWebsocketMessage["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, GetWebsocketMessage["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? getWebsocketMessageQueryKey(); | |
| - const query = useQuery({ | |
| - ...(getWebsocketMessageQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, GetWebsocketMessage["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const getWebsocketMessageSuspenseQueryKey = () => | |
| - [{ url: "/websocket/message" }] as const; | |
| -export type GetWebsocketMessageSuspenseQueryKey = ReturnType< | |
| - typeof getWebsocketMessageSuspenseQueryKey | |
| ->; | |
| -export function getWebsocketMessageSuspenseQueryOptions( | |
| - options: GetWebsocketMessage["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = getWebsocketMessageSuspenseQueryKey(); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - GetWebsocketMessage["data"], | |
| - GetWebsocketMessage["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/websocket/message`, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description Get websocket message | |
| - * @summary Get websocket message (This isn't implemented yet, emitted for swagger type) | |
| - * @link /websocket/message | |
| - */ | |
| -export function useGetWebsocketMessageSuspense< | |
| - TData = GetWebsocketMessage["response"], | |
| - TQueryKey extends QueryKey = GetWebsocketMessageSuspenseQueryKey, | |
| ->( | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - GetWebsocketMessage["response"], | |
| - GetWebsocketMessage["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: GetWebsocketMessage["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, GetWebsocketMessage["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? getWebsocketMessageSuspenseQueryKey(); | |
| - const query = useSuspenseQuery({ | |
| - ...(getWebsocketMessageSuspenseQueryOptions( | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, GetWebsocketMessage["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useListFulfillments.ts b/src/phoenix-generated/hooks/useListFulfillments.ts | |
| deleted file mode 100644 | |
| index 20961b46..00000000 | |
| --- a/src/phoenix-generated/hooks/useListFulfillments.ts | |
| +++ /dev/null | |
| @@ -1,174 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - ListFulfillments400, | |
| - ListFulfillments401, | |
| - ListFulfillments500, | |
| - ListFulfillmentsQueryParams, | |
| - ListFulfillmentsQueryResponse, | |
| -} from "../types/ListFulfillments"; | |
| - | |
| -type ListFulfillmentsClient = typeof client< | |
| - ListFulfillmentsQueryResponse, | |
| - ListFulfillments400 | ListFulfillments401 | ListFulfillments500, | |
| - never | |
| ->; | |
| -type ListFulfillments = { | |
| - data: ListFulfillmentsQueryResponse; | |
| - error: ListFulfillments400 | ListFulfillments401 | ListFulfillments500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: ListFulfillmentsQueryParams; | |
| - headerParams: never; | |
| - response: ListFulfillmentsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<ListFulfillmentsClient>[0]>; | |
| - return: Awaited<ReturnType<ListFulfillmentsClient>>; | |
| - }; | |
| -}; | |
| -export const listFulfillmentsQueryKey = ( | |
| - params?: ListFulfillments["queryParams"], | |
| -) => [{ url: "/fulfillment" }, ...(params ? [params] : [])] as const; | |
| -export type ListFulfillmentsQueryKey = ReturnType< | |
| - typeof listFulfillmentsQueryKey | |
| ->; | |
| -export function listFulfillmentsQueryOptions( | |
| - params?: ListFulfillments["queryParams"], | |
| - options: ListFulfillments["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listFulfillmentsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListFulfillments["data"], | |
| - ListFulfillments["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/fulfillment`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List fulfillments with optional filtering | |
| - * @summary List fulfillments | |
| - * @link /fulfillment | |
| - */ | |
| -export function useListFulfillments< | |
| - TData = ListFulfillments["response"], | |
| - TQueryData = ListFulfillments["response"], | |
| - TQueryKey extends QueryKey = ListFulfillmentsQueryKey, | |
| ->( | |
| - params?: ListFulfillments["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - ListFulfillments["response"], | |
| - ListFulfillments["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListFulfillments["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, ListFulfillments["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? listFulfillmentsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(listFulfillmentsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, ListFulfillments["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const listFulfillmentsSuspenseQueryKey = ( | |
| - params?: ListFulfillments["queryParams"], | |
| -) => [{ url: "/fulfillment" }, ...(params ? [params] : [])] as const; | |
| -export type ListFulfillmentsSuspenseQueryKey = ReturnType< | |
| - typeof listFulfillmentsSuspenseQueryKey | |
| ->; | |
| -export function listFulfillmentsSuspenseQueryOptions( | |
| - params?: ListFulfillments["queryParams"], | |
| - options: ListFulfillments["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listFulfillmentsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListFulfillments["data"], | |
| - ListFulfillments["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/fulfillment`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List fulfillments with optional filtering | |
| - * @summary List fulfillments | |
| - * @link /fulfillment | |
| - */ | |
| -export function useListFulfillmentsSuspense< | |
| - TData = ListFulfillments["response"], | |
| - TQueryKey extends QueryKey = ListFulfillmentsSuspenseQueryKey, | |
| ->( | |
| - params?: ListFulfillments["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - ListFulfillments["response"], | |
| - ListFulfillments["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListFulfillments["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, ListFulfillments["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listFulfillmentsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(listFulfillmentsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, ListFulfillments["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useListLoyaltyCustomers.ts b/src/phoenix-generated/hooks/useListLoyaltyCustomers.ts | |
| deleted file mode 100644 | |
| index 74bd1383..00000000 | |
| --- a/src/phoenix-generated/hooks/useListLoyaltyCustomers.ts | |
| +++ /dev/null | |
| @@ -1,183 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - ListLoyaltyCustomers400, | |
| - ListLoyaltyCustomers401, | |
| - ListLoyaltyCustomers422, | |
| - ListLoyaltyCustomers500, | |
| - ListLoyaltyCustomersQueryParams, | |
| - ListLoyaltyCustomersQueryResponse, | |
| -} from "../types/ListLoyaltyCustomers"; | |
| - | |
| -type ListLoyaltyCustomersClient = typeof client< | |
| - ListLoyaltyCustomersQueryResponse, | |
| - | ListLoyaltyCustomers400 | |
| - | ListLoyaltyCustomers401 | |
| - | ListLoyaltyCustomers422 | |
| - | ListLoyaltyCustomers500, | |
| - never | |
| ->; | |
| -type ListLoyaltyCustomers = { | |
| - data: ListLoyaltyCustomersQueryResponse; | |
| - error: | |
| - | ListLoyaltyCustomers400 | |
| - | ListLoyaltyCustomers401 | |
| - | ListLoyaltyCustomers422 | |
| - | ListLoyaltyCustomers500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: ListLoyaltyCustomersQueryParams; | |
| - headerParams: never; | |
| - response: ListLoyaltyCustomersQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<ListLoyaltyCustomersClient>[0]>; | |
| - return: Awaited<ReturnType<ListLoyaltyCustomersClient>>; | |
| - }; | |
| -}; | |
| -export const listLoyaltyCustomersQueryKey = ( | |
| - params?: ListLoyaltyCustomers["queryParams"], | |
| -) => [{ url: "/loyalty-customer" }, ...(params ? [params] : [])] as const; | |
| -export type ListLoyaltyCustomersQueryKey = ReturnType< | |
| - typeof listLoyaltyCustomersQueryKey | |
| ->; | |
| -export function listLoyaltyCustomersQueryOptions( | |
| - params?: ListLoyaltyCustomers["queryParams"], | |
| - options: ListLoyaltyCustomers["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listLoyaltyCustomersQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListLoyaltyCustomers["data"], | |
| - ListLoyaltyCustomers["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/loyalty-customer`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List loyalty customers | |
| - * @summary List loyalty customers | |
| - * @link /loyalty-customer | |
| - */ | |
| -export function useListLoyaltyCustomers< | |
| - TData = ListLoyaltyCustomers["response"], | |
| - TQueryData = ListLoyaltyCustomers["response"], | |
| - TQueryKey extends QueryKey = ListLoyaltyCustomersQueryKey, | |
| ->( | |
| - params?: ListLoyaltyCustomers["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - ListLoyaltyCustomers["response"], | |
| - ListLoyaltyCustomers["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListLoyaltyCustomers["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, ListLoyaltyCustomers["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listLoyaltyCustomersQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(listLoyaltyCustomersQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, ListLoyaltyCustomers["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const listLoyaltyCustomersSuspenseQueryKey = ( | |
| - params?: ListLoyaltyCustomers["queryParams"], | |
| -) => [{ url: "/loyalty-customer" }, ...(params ? [params] : [])] as const; | |
| -export type ListLoyaltyCustomersSuspenseQueryKey = ReturnType< | |
| - typeof listLoyaltyCustomersSuspenseQueryKey | |
| ->; | |
| -export function listLoyaltyCustomersSuspenseQueryOptions( | |
| - params?: ListLoyaltyCustomers["queryParams"], | |
| - options: ListLoyaltyCustomers["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listLoyaltyCustomersSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListLoyaltyCustomers["data"], | |
| - ListLoyaltyCustomers["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/loyalty-customer`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List loyalty customers | |
| - * @summary List loyalty customers | |
| - * @link /loyalty-customer | |
| - */ | |
| -export function useListLoyaltyCustomersSuspense< | |
| - TData = ListLoyaltyCustomers["response"], | |
| - TQueryKey extends QueryKey = ListLoyaltyCustomersSuspenseQueryKey, | |
| ->( | |
| - params?: ListLoyaltyCustomers["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - ListLoyaltyCustomers["response"], | |
| - ListLoyaltyCustomers["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListLoyaltyCustomers["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, ListLoyaltyCustomers["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listLoyaltyCustomersSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(listLoyaltyCustomersSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, ListLoyaltyCustomers["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useListOrderItemDecisions.ts b/src/phoenix-generated/hooks/useListOrderItemDecisions.ts | |
| deleted file mode 100644 | |
| index 3718a408..00000000 | |
| --- a/src/phoenix-generated/hooks/useListOrderItemDecisions.ts | |
| +++ /dev/null | |
| @@ -1,180 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - ListOrderItemDecisions400, | |
| - ListOrderItemDecisions401, | |
| - ListOrderItemDecisions500, | |
| - ListOrderItemDecisionsQueryParams, | |
| - ListOrderItemDecisionsQueryResponse, | |
| -} from "../types/ListOrderItemDecisions"; | |
| - | |
| -type ListOrderItemDecisionsClient = typeof client< | |
| - ListOrderItemDecisionsQueryResponse, | |
| - | ListOrderItemDecisions400 | |
| - | ListOrderItemDecisions401 | |
| - | ListOrderItemDecisions500, | |
| - never | |
| ->; | |
| -type ListOrderItemDecisions = { | |
| - data: ListOrderItemDecisionsQueryResponse; | |
| - error: | |
| - | ListOrderItemDecisions400 | |
| - | ListOrderItemDecisions401 | |
| - | ListOrderItemDecisions500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: ListOrderItemDecisionsQueryParams; | |
| - headerParams: never; | |
| - response: ListOrderItemDecisionsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<ListOrderItemDecisionsClient>[0]>; | |
| - return: Awaited<ReturnType<ListOrderItemDecisionsClient>>; | |
| - }; | |
| -}; | |
| -export const listOrderItemDecisionsQueryKey = ( | |
| - params?: ListOrderItemDecisions["queryParams"], | |
| -) => [{ url: "/order-item-decisions" }, ...(params ? [params] : [])] as const; | |
| -export type ListOrderItemDecisionsQueryKey = ReturnType< | |
| - typeof listOrderItemDecisionsQueryKey | |
| ->; | |
| -export function listOrderItemDecisionsQueryOptions( | |
| - params?: ListOrderItemDecisions["queryParams"], | |
| - options: ListOrderItemDecisions["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listOrderItemDecisionsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListOrderItemDecisions["data"], | |
| - ListOrderItemDecisions["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/order-item-decisions`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List order item decisions with optional filtering | |
| - * @summary List order item decisions | |
| - * @link /order-item-decisions | |
| - */ | |
| -export function useListOrderItemDecisions< | |
| - TData = ListOrderItemDecisions["response"], | |
| - TQueryData = ListOrderItemDecisions["response"], | |
| - TQueryKey extends QueryKey = ListOrderItemDecisionsQueryKey, | |
| ->( | |
| - params?: ListOrderItemDecisions["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - ListOrderItemDecisions["response"], | |
| - ListOrderItemDecisions["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListOrderItemDecisions["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, ListOrderItemDecisions["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listOrderItemDecisionsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(listOrderItemDecisionsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, ListOrderItemDecisions["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const listOrderItemDecisionsSuspenseQueryKey = ( | |
| - params?: ListOrderItemDecisions["queryParams"], | |
| -) => [{ url: "/order-item-decisions" }, ...(params ? [params] : [])] as const; | |
| -export type ListOrderItemDecisionsSuspenseQueryKey = ReturnType< | |
| - typeof listOrderItemDecisionsSuspenseQueryKey | |
| ->; | |
| -export function listOrderItemDecisionsSuspenseQueryOptions( | |
| - params?: ListOrderItemDecisions["queryParams"], | |
| - options: ListOrderItemDecisions["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listOrderItemDecisionsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListOrderItemDecisions["data"], | |
| - ListOrderItemDecisions["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/order-item-decisions`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List order item decisions with optional filtering | |
| - * @summary List order item decisions | |
| - * @link /order-item-decisions | |
| - */ | |
| -export function useListOrderItemDecisionsSuspense< | |
| - TData = ListOrderItemDecisions["response"], | |
| - TQueryKey extends QueryKey = ListOrderItemDecisionsSuspenseQueryKey, | |
| ->( | |
| - params?: ListOrderItemDecisions["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - ListOrderItemDecisions["response"], | |
| - ListOrderItemDecisions["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListOrderItemDecisions["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, ListOrderItemDecisions["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listOrderItemDecisionsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(listOrderItemDecisionsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, ListOrderItemDecisions["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useListStorefronts.ts b/src/phoenix-generated/hooks/useListStorefronts.ts | |
| deleted file mode 100644 | |
| index 1813a630..00000000 | |
| --- a/src/phoenix-generated/hooks/useListStorefronts.ts | |
| +++ /dev/null | |
| @@ -1,173 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - ListStorefronts401, | |
| - ListStorefronts500, | |
| - ListStorefrontsQueryParams, | |
| - ListStorefrontsQueryResponse, | |
| -} from "../types/ListStorefronts"; | |
| - | |
| -type ListStorefrontsClient = typeof client< | |
| - ListStorefrontsQueryResponse, | |
| - ListStorefronts401 | ListStorefronts500, | |
| - never | |
| ->; | |
| -type ListStorefronts = { | |
| - data: ListStorefrontsQueryResponse; | |
| - error: ListStorefronts401 | ListStorefronts500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: ListStorefrontsQueryParams; | |
| - headerParams: never; | |
| - response: ListStorefrontsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<ListStorefrontsClient>[0]>; | |
| - return: Awaited<ReturnType<ListStorefrontsClient>>; | |
| - }; | |
| -}; | |
| -export const listStorefrontsQueryKey = ( | |
| - params?: ListStorefronts["queryParams"], | |
| -) => [{ url: "/storefronts" }, ...(params ? [params] : [])] as const; | |
| -export type ListStorefrontsQueryKey = ReturnType< | |
| - typeof listStorefrontsQueryKey | |
| ->; | |
| -export function listStorefrontsQueryOptions( | |
| - params?: ListStorefronts["queryParams"], | |
| - options: ListStorefronts["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listStorefrontsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListStorefronts["data"], | |
| - ListStorefronts["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List storefronts with optional filtering by cohort_id and active status | |
| - * @summary List storefronts | |
| - * @link /storefronts | |
| - */ | |
| -export function useListStorefronts< | |
| - TData = ListStorefronts["response"], | |
| - TQueryData = ListStorefronts["response"], | |
| - TQueryKey extends QueryKey = ListStorefrontsQueryKey, | |
| ->( | |
| - params?: ListStorefronts["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - ListStorefronts["response"], | |
| - ListStorefronts["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListStorefronts["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, ListStorefronts["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? listStorefrontsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(listStorefrontsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, ListStorefronts["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const listStorefrontsSuspenseQueryKey = ( | |
| - params?: ListStorefronts["queryParams"], | |
| -) => [{ url: "/storefronts" }, ...(params ? [params] : [])] as const; | |
| -export type ListStorefrontsSuspenseQueryKey = ReturnType< | |
| - typeof listStorefrontsSuspenseQueryKey | |
| ->; | |
| -export function listStorefrontsSuspenseQueryOptions( | |
| - params?: ListStorefronts["queryParams"], | |
| - options: ListStorefronts["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listStorefrontsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListStorefronts["data"], | |
| - ListStorefronts["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/storefronts`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List storefronts with optional filtering by cohort_id and active status | |
| - * @summary List storefronts | |
| - * @link /storefronts | |
| - */ | |
| -export function useListStorefrontsSuspense< | |
| - TData = ListStorefronts["response"], | |
| - TQueryKey extends QueryKey = ListStorefrontsSuspenseQueryKey, | |
| ->( | |
| - params?: ListStorefronts["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - ListStorefronts["response"], | |
| - ListStorefronts["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListStorefronts["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, ListStorefronts["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listStorefrontsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(listStorefrontsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, ListStorefronts["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useListTransactionItems.ts b/src/phoenix-generated/hooks/useListTransactionItems.ts | |
| deleted file mode 100644 | |
| index 104454de..00000000 | |
| --- a/src/phoenix-generated/hooks/useListTransactionItems.ts | |
| +++ /dev/null | |
| @@ -1,178 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - ListTransactionItems400, | |
| - ListTransactionItems401, | |
| - ListTransactionItems500, | |
| - ListTransactionItemsQueryParams, | |
| - ListTransactionItemsQueryResponse, | |
| -} from "../types/ListTransactionItems"; | |
| - | |
| -type ListTransactionItemsClient = typeof client< | |
| - ListTransactionItemsQueryResponse, | |
| - ListTransactionItems400 | ListTransactionItems401 | ListTransactionItems500, | |
| - never | |
| ->; | |
| -type ListTransactionItems = { | |
| - data: ListTransactionItemsQueryResponse; | |
| - error: | |
| - | ListTransactionItems400 | |
| - | ListTransactionItems401 | |
| - | ListTransactionItems500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: ListTransactionItemsQueryParams; | |
| - headerParams: never; | |
| - response: ListTransactionItemsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<ListTransactionItemsClient>[0]>; | |
| - return: Awaited<ReturnType<ListTransactionItemsClient>>; | |
| - }; | |
| -}; | |
| -export const listTransactionItemsQueryKey = ( | |
| - params?: ListTransactionItems["queryParams"], | |
| -) => [{ url: "/transaction-item" }, ...(params ? [params] : [])] as const; | |
| -export type ListTransactionItemsQueryKey = ReturnType< | |
| - typeof listTransactionItemsQueryKey | |
| ->; | |
| -export function listTransactionItemsQueryOptions( | |
| - params?: ListTransactionItems["queryParams"], | |
| - options: ListTransactionItems["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listTransactionItemsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListTransactionItems["data"], | |
| - ListTransactionItems["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction-item`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List transaction items | |
| - * @summary List transaction items | |
| - * @link /transaction-item | |
| - */ | |
| -export function useListTransactionItems< | |
| - TData = ListTransactionItems["response"], | |
| - TQueryData = ListTransactionItems["response"], | |
| - TQueryKey extends QueryKey = ListTransactionItemsQueryKey, | |
| ->( | |
| - params?: ListTransactionItems["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - ListTransactionItems["response"], | |
| - ListTransactionItems["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListTransactionItems["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, ListTransactionItems["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listTransactionItemsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(listTransactionItemsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, ListTransactionItems["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const listTransactionItemsSuspenseQueryKey = ( | |
| - params?: ListTransactionItems["queryParams"], | |
| -) => [{ url: "/transaction-item" }, ...(params ? [params] : [])] as const; | |
| -export type ListTransactionItemsSuspenseQueryKey = ReturnType< | |
| - typeof listTransactionItemsSuspenseQueryKey | |
| ->; | |
| -export function listTransactionItemsSuspenseQueryOptions( | |
| - params?: ListTransactionItems["queryParams"], | |
| - options: ListTransactionItems["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listTransactionItemsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListTransactionItems["data"], | |
| - ListTransactionItems["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction-item`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List transaction items | |
| - * @summary List transaction items | |
| - * @link /transaction-item | |
| - */ | |
| -export function useListTransactionItemsSuspense< | |
| - TData = ListTransactionItems["response"], | |
| - TQueryKey extends QueryKey = ListTransactionItemsSuspenseQueryKey, | |
| ->( | |
| - params?: ListTransactionItems["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - ListTransactionItems["response"], | |
| - ListTransactionItems["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListTransactionItems["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, ListTransactionItems["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listTransactionItemsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(listTransactionItemsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, ListTransactionItems["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/useListTransactions.ts b/src/phoenix-generated/hooks/useListTransactions.ts | |
| deleted file mode 100644 | |
| index 7e5861db..00000000 | |
| --- a/src/phoenix-generated/hooks/useListTransactions.ts | |
| +++ /dev/null | |
| @@ -1,174 +0,0 @@ | |
| -import type { | |
| - QueryKey, | |
| - QueryObserverOptions, | |
| - UseQueryResult, | |
| - UseSuspenseQueryOptions, | |
| - UseSuspenseQueryResult, | |
| -} from "@tanstack/react-query"; | |
| -import { | |
| - queryOptions, | |
| - useQuery, | |
| - useSuspenseQuery, | |
| -} from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - ListTransactions400, | |
| - ListTransactions401, | |
| - ListTransactions500, | |
| - ListTransactionsQueryParams, | |
| - ListTransactionsQueryResponse, | |
| -} from "../types/ListTransactions"; | |
| - | |
| -type ListTransactionsClient = typeof client< | |
| - ListTransactionsQueryResponse, | |
| - ListTransactions400 | ListTransactions401 | ListTransactions500, | |
| - never | |
| ->; | |
| -type ListTransactions = { | |
| - data: ListTransactionsQueryResponse; | |
| - error: ListTransactions400 | ListTransactions401 | ListTransactions500; | |
| - request: never; | |
| - pathParams: never; | |
| - queryParams: ListTransactionsQueryParams; | |
| - headerParams: never; | |
| - response: ListTransactionsQueryResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<ListTransactionsClient>[0]>; | |
| - return: Awaited<ReturnType<ListTransactionsClient>>; | |
| - }; | |
| -}; | |
| -export const listTransactionsQueryKey = ( | |
| - params?: ListTransactions["queryParams"], | |
| -) => [{ url: "/transaction" }, ...(params ? [params] : [])] as const; | |
| -export type ListTransactionsQueryKey = ReturnType< | |
| - typeof listTransactionsQueryKey | |
| ->; | |
| -export function listTransactionsQueryOptions( | |
| - params?: ListTransactions["queryParams"], | |
| - options: ListTransactions["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listTransactionsQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListTransactions["data"], | |
| - ListTransactions["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List transactions | |
| - * @summary List transactions | |
| - * @link /transaction | |
| - */ | |
| -export function useListTransactions< | |
| - TData = ListTransactions["response"], | |
| - TQueryData = ListTransactions["response"], | |
| - TQueryKey extends QueryKey = ListTransactionsQueryKey, | |
| ->( | |
| - params?: ListTransactions["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - QueryObserverOptions< | |
| - ListTransactions["response"], | |
| - ListTransactions["error"], | |
| - TData, | |
| - TQueryData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListTransactions["client"]["parameters"]; | |
| - } = {}, | |
| -): UseQueryResult<TData, ListTransactions["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = queryOptions?.queryKey ?? listTransactionsQueryKey(params); | |
| - const query = useQuery({ | |
| - ...(listTransactionsQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as QueryObserverOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<QueryObserverOptions, "queryKey">), | |
| - }) as UseQueryResult<TData, ListTransactions["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| -export const listTransactionsSuspenseQueryKey = ( | |
| - params?: ListTransactions["queryParams"], | |
| -) => [{ url: "/transaction" }, ...(params ? [params] : [])] as const; | |
| -export type ListTransactionsSuspenseQueryKey = ReturnType< | |
| - typeof listTransactionsSuspenseQueryKey | |
| ->; | |
| -export function listTransactionsSuspenseQueryOptions( | |
| - params?: ListTransactions["queryParams"], | |
| - options: ListTransactions["client"]["parameters"] = {}, | |
| -) { | |
| - const queryKey = listTransactionsSuspenseQueryKey(params); | |
| - return queryOptions({ | |
| - queryKey, | |
| - queryFn: async () => { | |
| - const res = await client< | |
| - ListTransactions["data"], | |
| - ListTransactions["error"] | |
| - >({ | |
| - method: "get", | |
| - url: `/transaction`, | |
| - params, | |
| - ...options, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - }); | |
| -} | |
| -/** | |
| - * @description List transactions | |
| - * @summary List transactions | |
| - * @link /transaction | |
| - */ | |
| -export function useListTransactionsSuspense< | |
| - TData = ListTransactions["response"], | |
| - TQueryKey extends QueryKey = ListTransactionsSuspenseQueryKey, | |
| ->( | |
| - params?: ListTransactions["queryParams"], | |
| - options: { | |
| - query?: Partial< | |
| - UseSuspenseQueryOptions< | |
| - ListTransactions["response"], | |
| - ListTransactions["error"], | |
| - TData, | |
| - TQueryKey | |
| - > | |
| - >; | |
| - client?: ListTransactions["client"]["parameters"]; | |
| - } = {}, | |
| -): UseSuspenseQueryResult<TData, ListTransactions["error"]> & { | |
| - queryKey: TQueryKey; | |
| -} { | |
| - const { query: queryOptions, client: clientOptions = {} } = options ?? {}; | |
| - const queryKey = | |
| - queryOptions?.queryKey ?? listTransactionsSuspenseQueryKey(params); | |
| - const query = useSuspenseQuery({ | |
| - ...(listTransactionsSuspenseQueryOptions( | |
| - params, | |
| - clientOptions, | |
| - ) as unknown as UseSuspenseQueryOptions), | |
| - queryKey, | |
| - ...(queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">), | |
| - }) as UseSuspenseQueryResult<TData, ListTransactions["error"]> & { | |
| - queryKey: TQueryKey; | |
| - }; | |
| - query.queryKey = queryKey as TQueryKey; | |
| - return query; | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/usePatchFulfillmentId.ts b/src/phoenix-generated/hooks/usePatchFulfillmentId.ts | |
| deleted file mode 100644 | |
| index be6d98a3..00000000 | |
| --- a/src/phoenix-generated/hooks/usePatchFulfillmentId.ts | |
| +++ /dev/null | |
| @@ -1,78 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - PatchFulfillmentId400, | |
| - PatchFulfillmentId401, | |
| - PatchFulfillmentId404, | |
| - PatchFulfillmentId422, | |
| - PatchFulfillmentId500, | |
| - PatchFulfillmentIdMutationRequest, | |
| - PatchFulfillmentIdMutationResponse, | |
| - PatchFulfillmentIdPathParams, | |
| -} from "../types/PatchFulfillmentId"; | |
| - | |
| -type PatchFulfillmentIdClient = typeof client< | |
| - PatchFulfillmentIdMutationResponse, | |
| - | PatchFulfillmentId400 | |
| - | PatchFulfillmentId401 | |
| - | PatchFulfillmentId404 | |
| - | PatchFulfillmentId422 | |
| - | PatchFulfillmentId500, | |
| - PatchFulfillmentIdMutationRequest | |
| ->; | |
| -type PatchFulfillmentId = { | |
| - data: PatchFulfillmentIdMutationResponse; | |
| - error: | |
| - | PatchFulfillmentId400 | |
| - | PatchFulfillmentId401 | |
| - | PatchFulfillmentId404 | |
| - | PatchFulfillmentId422 | |
| - | PatchFulfillmentId500; | |
| - request: PatchFulfillmentIdMutationRequest; | |
| - pathParams: PatchFulfillmentIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: PatchFulfillmentIdMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<PatchFulfillmentIdClient>[0]>; | |
| - return: Awaited<ReturnType<PatchFulfillmentIdClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Update an existing fulfillment | |
| - * @summary Update fulfillment | |
| - * @link /fulfillment/:id | |
| - */ | |
| -export function usePatchFulfillmentId( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - PatchFulfillmentId["response"], | |
| - PatchFulfillmentId["error"], | |
| - { | |
| - id: PatchFulfillmentIdPathParams["id"]; | |
| - data?: PatchFulfillmentId["request"]; | |
| - } | |
| - >; | |
| - client?: PatchFulfillmentId["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ id, data }) => { | |
| - const res = await client< | |
| - PatchFulfillmentId["data"], | |
| - PatchFulfillmentId["error"], | |
| - PatchFulfillmentId["request"] | |
| - >({ | |
| - method: "patch", | |
| - url: `/fulfillment/${id}`, | |
| - data, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/usePatchStorefrontsId.ts b/src/phoenix-generated/hooks/usePatchStorefrontsId.ts | |
| deleted file mode 100644 | |
| index 18f68bd4..00000000 | |
| --- a/src/phoenix-generated/hooks/usePatchStorefrontsId.ts | |
| +++ /dev/null | |
| @@ -1,78 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - PatchStorefrontsId400, | |
| - PatchStorefrontsId401, | |
| - PatchStorefrontsId404, | |
| - PatchStorefrontsId422, | |
| - PatchStorefrontsId500, | |
| - PatchStorefrontsIdMutationRequest, | |
| - PatchStorefrontsIdMutationResponse, | |
| - PatchStorefrontsIdPathParams, | |
| -} from "../types/PatchStorefrontsId"; | |
| - | |
| -type PatchStorefrontsIdClient = typeof client< | |
| - PatchStorefrontsIdMutationResponse, | |
| - | PatchStorefrontsId400 | |
| - | PatchStorefrontsId401 | |
| - | PatchStorefrontsId404 | |
| - | PatchStorefrontsId422 | |
| - | PatchStorefrontsId500, | |
| - PatchStorefrontsIdMutationRequest | |
| ->; | |
| -type PatchStorefrontsId = { | |
| - data: PatchStorefrontsIdMutationResponse; | |
| - error: | |
| - | PatchStorefrontsId400 | |
| - | PatchStorefrontsId401 | |
| - | PatchStorefrontsId404 | |
| - | PatchStorefrontsId422 | |
| - | PatchStorefrontsId500; | |
| - request: PatchStorefrontsIdMutationRequest; | |
| - pathParams: PatchStorefrontsIdPathParams; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: PatchStorefrontsIdMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<PatchStorefrontsIdClient>[0]>; | |
| - return: Awaited<ReturnType<PatchStorefrontsIdClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Update an existing storefront | |
| - * @summary Update storefront | |
| - * @link /storefronts/:id | |
| - */ | |
| -export function usePatchStorefrontsId( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - PatchStorefrontsId["response"], | |
| - PatchStorefrontsId["error"], | |
| - { | |
| - id: PatchStorefrontsIdPathParams["id"]; | |
| - data?: PatchStorefrontsId["request"]; | |
| - } | |
| - >; | |
| - client?: PatchStorefrontsId["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - return useMutation({ | |
| - mutationFn: async ({ id, data }) => { | |
| - const res = await client< | |
| - PatchStorefrontsId["data"], | |
| - PatchStorefrontsId["error"], | |
| - PatchStorefrontsId["request"] | |
| - >({ | |
| - method: "patch", | |
| - url: `/storefronts/${id}`, | |
| - data, | |
| - ...clientOptions, | |
| - }); | |
| - return res.data; | |
| - }, | |
| - ...mutationOptions, | |
| - }); | |
| -} | |
| diff --git a/src/phoenix-generated/hooks/usePostCustomer.ts b/src/phoenix-generated/hooks/usePostCustomer.ts | |
| deleted file mode 100644 | |
| index 1d11b3e7..00000000 | |
| --- a/src/phoenix-generated/hooks/usePostCustomer.ts | |
| +++ /dev/null | |
| @@ -1,66 +0,0 @@ | |
| -import type { UseMutationOptions } from "@tanstack/react-query"; | |
| -import { useMutation } from "@tanstack/react-query"; | |
| -import client from "../../config/phoenix-client"; | |
| -import type { | |
| - PostCustomer400, | |
| - PostCustomer401, | |
| - PostCustomer422, | |
| - PostCustomer500, | |
| - PostCustomerMutationRequest, | |
| - PostCustomerMutationResponse, | |
| -} from "../types/PostCustomer"; | |
| - | |
| -type PostCustomerClient = typeof client< | |
| - PostCustomerMutationResponse, | |
| - PostCustomer400 | PostCustomer401 | PostCustomer422 | PostCustomer500, | |
| - PostCustomerMutationRequest | |
| ->; | |
| -type PostCustomer = { | |
| - data: PostCustomerMutationResponse; | |
| - error: PostCustomer400 | PostCustomer401 | PostCustomer422 | PostCustomer500; | |
| - request: PostCustomerMutationRequest; | |
| - pathParams: never; | |
| - queryParams: never; | |
| - headerParams: never; | |
| - response: PostCustomerMutationResponse; | |
| - client: { | |
| - parameters: Partial<Parameters<PostCustomerClient>[0]>; | |
| - return: Awaited<ReturnType<PostCustomerClient>>; | |
| - }; | |
| -}; | |
| -/** | |
| - * @description Create a new customer | |
| - * @summary Create customer | |
| - * @link /customer | |
| - */ | |
| -export function usePostCustomer( | |
| - options: { | |
| - mutation?: UseMutationOptions< | |
| - PostCustomer["response"], | |
| - PostCustomer["error"], | |
| - { | |
| - data: PostCustomer["request"]; | |
| - } | |
| - >; | |
| - client?: PostCustomer["client"]["parameters"]; | |
| - } = {}, | |
| -) { | |
| - const { mutation: mutationOptions, client: clientOptions = {} } = | |
| - options ?? {}; | |
| - ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment