Created
February 13, 2026 16:47
-
-
Save jay-babu/081099159c8a280c7a6b944bd5f4b9a4 to your computer and use it in GitHub Desktop.
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 68b29ba4b..28754bf1a 100644 | |
| --- a/.claude/settings.local.json | |
| +++ b/.claude/settings.local.json | |
| @@ -25,7 +25,11 @@ | |
| "Bash(npx agent-browser:*)", | |
| "Bash(source .env)", | |
| "Bash(npx stably test:*)", | |
| - "mcp__context7__query-docs" | |
| + "mcp__context7__query-docs", | |
| + "Bash(npm view:*)", | |
| + "Bash(python3:*)", | |
| + "Bash(npm install:*)", | |
| + "Bash(npx storybook@9 upgrade:*)" | |
| ], | |
| "deny": [] | |
| }, | |
| diff --git a/.github/workflows/stably-test.yml b/.github/workflows/stably-test.yml | |
| index 825c85de4..3b71f22be 100644 | |
| --- a/.github/workflows/stably-test.yml | |
| +++ b/.github/workflows/stably-test.yml | |
| @@ -30,23 +30,23 @@ jobs: | |
| continue-on-error: true | |
| env: | |
| STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }} | |
| - STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }} | |
| + STABLY_PROJECT_ID: ${{ vars.STABLY_PROJECT_ID }} | |
| email: ${{ vars.EMAIL }} | |
| password: ${{ secrets.PASSWORD }} | |
| employeePin: ${{ secrets.EMPLOYEE_PIN }} | |
| TEST_BASE_URL: ${{ vars.TEST_BASE_URL }} | |
| - run: npx stably test | |
| + run: npx stably test --verbose | |
| - name: Fix failing tests (optional) | |
| if: steps.test.outcome == 'failure' | |
| env: | |
| STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }} | |
| - STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }} | |
| + STABLY_PROJECT_ID: ${{ vars.STABLY_PROJECT_ID }} | |
| email: ${{ vars.EMAIL }} | |
| password: ${{ secrets.PASSWORD }} | |
| employeePin: ${{ secrets.EMPLOYEE_PIN }} | |
| TEST_BASE_URL: ${{ vars.TEST_BASE_URL }} | |
| - run: npx stably fix | |
| + run: npx stably fix --verbose | |
| - name: Fail if tests failed | |
| if: steps.test.outcome == 'failure' | |
| diff --git a/.storybook/main.ts b/.storybook/main.ts | |
| index 1f618666a..c754b5e40 100644 | |
| --- a/.storybook/main.ts | |
| +++ b/.storybook/main.ts | |
| @@ -1,4 +1,3 @@ | |
| -import { withoutVitePlugins } from "@storybook/builder-vite"; | |
| import type { StorybookConfig } from "@storybook/react-vite"; | |
| import path from "node:path"; | |
| import tsconfigPaths from "vite-tsconfig-paths"; | |
| @@ -8,9 +7,8 @@ const config: StorybookConfig = { | |
| addons: [ | |
| "@storybook/addon-onboarding", | |
| "@storybook/addon-links", | |
| - "@storybook/addon-essentials", | |
| "@chromatic-com/storybook", | |
| - "@storybook/addon-interactions", | |
| + "@storybook/addon-docs" | |
| ], | |
| framework: { | |
| name: "@storybook/react-vite", | |
| @@ -18,17 +16,6 @@ const config: StorybookConfig = { | |
| }, | |
| staticDirs: ["../public"], | |
| viteFinal: async (config) => { | |
| - const plugins = await withoutVitePlugins(config.plugins, [ | |
| - "vite-plugin-pwa", | |
| - "vite-plugin-pwa:info", | |
| - "vite-plugin-pwa:build", | |
| - "vite-plugin-pwa:dev-sw", | |
| - "vite-plugin-pwa:pwa-assets", | |
| - "vite-plugin-pwa:register", | |
| - "vite-plugin-eslint", | |
| - "@mdx-js/rollup", | |
| - ]); | |
| - console.log(plugins); | |
| return { | |
| ...config, | |
| resolve: { | |
| @@ -47,7 +34,7 @@ const config: StorybookConfig = { | |
| optimizeDeps: { | |
| ...config.optimizeDeps, | |
| entries: [ | |
| - `${path.relative(config.root, path.resolve(__dirname, "../src"))}/**/*.stories.tsx`, | |
| + `${path.relative(config.root!, path.resolve(__dirname, "../src"))}/**/*.stories.tsx`, | |
| ], | |
| include: [...(config.optimizeDeps?.include ?? [])], | |
| exclude: ["node_modules/.cache/storybook"], | |
| @@ -58,7 +45,7 @@ const config: StorybookConfig = { | |
| ...config.build?.rollupOptions, | |
| }, | |
| }, | |
| - plugins: [...plugins, tsconfigPaths()], | |
| + plugins: [...(config.plugins ?? []), tsconfigPaths()], | |
| }; | |
| }, | |
| }; | |
| diff --git a/.storybook/preview.ts b/.storybook/preview.ts | |
| index 66dfe5ad2..788b3631b 100644 | |
| --- a/.storybook/preview.ts | |
| +++ b/.storybook/preview.ts | |
| @@ -1,4 +1,4 @@ | |
| -import type { Preview } from "@storybook/react"; | |
| +import type { Preview } from "@storybook/react-vite"; | |
| import { initialize, mswLoader } from "msw-storybook-addon"; | |
| import { handlers as generatedHandlers } from "../src/generated/msw/handlers"; | |
| import "../src/index.css"; // replace with the name of your tailwind css file | |
| diff --git a/package.json b/package.json | |
| index 2222f8489..98d01aa7b 100644 | |
| --- a/package.json | |
| +++ b/package.json | |
| @@ -29,6 +29,7 @@ | |
| "@intercom/messenger-js-sdk": "^0.0.18", | |
| "@mdx-js/react": "^3.1.0", | |
| "@mdx-js/rollup": "^3.1.0", | |
| + "@point-of-sale/receipt-printer-encoder": "^3.0.3", | |
| "@point-of-sale/webhid-barcode-scanner": "^1.2.1", | |
| "@radix-ui/react-accordion": "^1.2.0", | |
| "@radix-ui/react-alert-dialog": "^1.1.1", | |
| @@ -111,6 +112,7 @@ | |
| "re-resizable": "^6.9.11", | |
| "react": "^18.2.0", | |
| "react-apexcharts": "1.4.1", | |
| + "react-confetti": "^6.4.0", | |
| "react-credit-cards-2": "^1.0.2", | |
| "react-day-picker": "^9.11.0", | |
| "react-dom": "^18.2.0", | |
| @@ -139,7 +141,6 @@ | |
| "swagger-typescript-api": "^13.0.3", | |
| "tailwind-merge": "^2.3.0", | |
| "tailwindcss-animate": "^1.0.7", | |
| - "@point-of-sale/receipt-printer-encoder": "^3.0.3", | |
| "typeid-js": "^1.2.0", | |
| "typescript": "^5.3.3", | |
| "use-debounce": "^10.0.0", | |
| @@ -147,8 +148,8 @@ | |
| "usehooks-ts": "^2.16.0", | |
| "uuid": "^9.0.1", | |
| "vaul": "^0.9.2", | |
| - "vite": "^5.4.19", | |
| - "vite-tsconfig-paths": "^4.3.1", | |
| + "vite": "^7.3.1", | |
| + "vite-tsconfig-paths": "^6.1.0", | |
| "web-vitals": "^2.1.4", | |
| "yup": "^1.2.0", | |
| "zod": "^3.23.8" | |
| @@ -156,6 +157,7 @@ | |
| "scripts": { | |
| "start": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite", | |
| "build": "tsc && vite build", | |
| + "preview": "vite preview --port 3000", | |
| "build:prod": "tsc && vite build --mode production", | |
| "build:gamma": "tsc && vite build --mode staging", | |
| "test": "npx vitest", | |
| @@ -183,8 +185,7 @@ | |
| ] | |
| }, | |
| "devDependencies": { | |
| - "@chakra-ui/storybook-addon": "^5.1.0", | |
| - "@chromatic-com/storybook": "^1.5.0", | |
| + "@chromatic-com/storybook": "^4.1.3", | |
| "@emotion/styled": "^11.14.0", | |
| "@eslint/compat": "^1.2.9", | |
| "@eslint/eslintrc": "^3.3.1", | |
| @@ -207,17 +208,12 @@ | |
| "@pulumi/pulumi": "^3.113.0", | |
| "@sentry/vite-plugin": "^2.16.1", | |
| "@stablyai/playwright-test": "^2.0.13", | |
| - "@storybook/addon-essentials": "^8.1.0", | |
| - "@storybook/addon-interactions": "^8.1.0", | |
| - "@storybook/addon-links": "^8.1.0", | |
| - "@storybook/addon-onboarding": "^1.0.10", | |
| - "@storybook/blocks": "^8.1.0", | |
| - "@storybook/react": "^8.1.0", | |
| - "@storybook/react-vite": "^8.1.0", | |
| - "@storybook/react-webpack5": "^8.1.0", | |
| - "@storybook/test": "^8.1.0", | |
| - "@storybook/test-runner": "^0.16.0", | |
| - "@storybook/testing-library": "^0.2.2", | |
| + "@storybook/addon-docs": "9.1.17", | |
| + "@storybook/addon-links": "9.1.17", | |
| + "@storybook/addon-onboarding": "9.1.17", | |
| + "@storybook/react-vite": "9.1.17", | |
| + "@storybook/react-webpack5": "9.1.17", | |
| + "@storybook/test-runner": "^0.23.0", | |
| "@tailwindcss/forms": "^0.5.7", | |
| "@testing-library/dom": "^10.1.0", | |
| "@testing-library/jest-dom": "^5.16.5", | |
| @@ -229,8 +225,10 @@ | |
| "@types/lodash-es": "^4.17.12", | |
| "@types/node": "^22.0.0", | |
| "@types/papaparse": "^5.3.16", | |
| + "@types/qs": "^6.14.0", | |
| "@types/react": "^18.2.14", | |
| "@types/react-dom": "^18.2.6", | |
| + "@types/uuid": "^10.0.0", | |
| "@types/w3c-web-usb": "^1.0.10", | |
| "@typescript-eslint/eslint-plugin": "^8.32.1", | |
| "@vitest/coverage-v8": "^3.1.4", | |
| @@ -240,7 +238,7 @@ | |
| "eslint": "^9.26.0", | |
| "eslint-config-prettier": "^8.9.0", | |
| "eslint-plugin-react-hooks": "5.2.0", | |
| - "eslint-plugin-storybook": "^0.6.15", | |
| + "eslint-plugin-storybook": "9.1.17", | |
| "fake-indexeddb": "^6.2.4", | |
| "http-server": "^14.1.1", | |
| "husky": "^8.0.3", | |
| @@ -252,13 +250,13 @@ | |
| "prettier": "^3.8.1", | |
| "prettier-plugin-organize-imports": "^4.3.0", | |
| "prop-types": "^15.8.1", | |
| - "storybook": "^8.6.15", | |
| + "storybook": "9.1.17", | |
| "tailwindcss": "^3.4.1", | |
| "ts-jest": "^29.1.4", | |
| "tsx": "^4.20.5", | |
| - "vite-plugin-checker": "^0.6.4", | |
| + "vite-plugin-checker": "^0.12.0", | |
| "vite-plugin-eslint": "^1.8.1", | |
| - "vite-plugin-pwa": "^1.0.3", | |
| + "vite-plugin-pwa": "^1.2.0", | |
| "vite-plugin-wasm": "^3.5.0", | |
| "vitest": "^3.1.4", | |
| "wait-on": "^7.2.0", | |
| diff --git a/playwright.config.ts b/playwright.config.ts | |
| index 026c59ada..985b32978 100644 | |
| --- a/playwright.config.ts | |
| +++ b/playwright.config.ts | |
| @@ -25,14 +25,16 @@ const isLocalhost = baseURL === "http://localhost:3000"; | |
| */ | |
| export default defineConfig({ | |
| testDir: "./e2e", | |
| + /* Ignore seed files - they are used for test generation setup, not actual tests */ | |
| + testIgnore: ["**/*seed*.spec.ts"], | |
| /* Run tests in files in parallel */ | |
| fullyParallel: true, | |
| /* Fail the build on CI if you accidentally left test.only in the source code. */ | |
| forbidOnly: !!process.env.CI, | |
| /* Retry on CI only */ | |
| retries: process.env.CI ? 2 : 0, | |
| - /* Opt out of parallel tests on CI. */ | |
| - workers: process.env.CI ? 1 : undefined, | |
| + /* Run tests in parallel with 2 workers on CI. */ | |
| + workers: process.env.CI ? 2 : undefined, | |
| /* Reporter to use. See https://playwright.dev/docs/test-reporters */ | |
| reporter: [ | |
| ["html"], | |
| @@ -63,9 +65,12 @@ export default defineConfig({ | |
| /* Run your local dev server before starting the tests - skip if using external URL */ | |
| webServer: isLocalhost | |
| ? { | |
| + // Use production build + preview server instead of dev server | |
| + // This avoids service worker flakiness that only occurs with the Vite dev server | |
| command: "npm run start", | |
| url: "http://localhost:3000", | |
| reuseExistingServer: !process.env.CI, | |
| + timeout: 120000, | |
| } | |
| : undefined, | |
| }); | |
| diff --git a/src/components/Auth/AuthorizationFlowForms/EnterEmployeePinForm.stories.tsx b/src/components/Auth/AuthorizationFlowForms/EnterEmployeePinForm.stories.tsx | |
| index 45680df20..d6ff8e98b 100644 | |
| --- a/src/components/Auth/AuthorizationFlowForms/EnterEmployeePinForm.stories.tsx | |
| +++ b/src/components/Auth/AuthorizationFlowForms/EnterEmployeePinForm.stories.tsx | |
| @@ -1,5 +1,5 @@ | |
| -import { action } from "@storybook/addon-actions"; | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| +import { action } from "storybook/actions"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| import { UserDTO } from "model/data-contracts"; | |
| import { useState } from "react"; | |
| import { EnterEmployeePinForm } from "./EnterEmployeePinForm"; | |
| diff --git a/src/components/SalesScreenComponents/Modals/DriversLicenseScannerModal/DriversLicenseScannerModal.stories.tsx b/src/components/SalesScreenComponents/Modals/DriversLicenseScannerModal/DriversLicenseScannerModal.stories.tsx | |
| index 16e8faed3..1a99f6365 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/DriversLicenseScannerModal/DriversLicenseScannerModal.stories.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/DriversLicenseScannerModal/DriversLicenseScannerModal.stories.tsx | |
| @@ -1,6 +1,6 @@ | |
| import { ChakraProvider } from "@chakra-ui/react"; | |
| -import type { Meta, StoryObj } from "@storybook/react"; | |
| -import { fn } from "@storybook/test"; | |
| +import type { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { fn } from "storybook/test"; | |
| import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | |
| import { MockEntityProvider } from "src/test/mocks/entityProvider"; | |
| import { DriversLicenseScannerModal } from "./DriversLicenseScannerModal"; | |
| diff --git a/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx b/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx | |
| index de8545586..9be658046 100644 | |
| --- a/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx | |
| +++ b/src/components/SalesScreenComponents/Modals/payments/PayWithHouseAccount.stories.tsx | |
| @@ -1,6 +1,6 @@ | |
| -import { action } from "@storybook/addon-actions"; | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, within } from "@storybook/test"; | |
| +import { action } from "storybook/actions"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, within } from "storybook/test"; | |
| import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | |
| import { http, HttpResponse } from "msw"; | |
| import { useState } from "react"; | |
| diff --git a/src/components/common/BulkActionProgress/BulkActionProgress.stories.tsx b/src/components/common/BulkActionProgress/BulkActionProgress.stories.tsx | |
| index 58338a6fa..3d01baaeb 100644 | |
| --- a/src/components/common/BulkActionProgress/BulkActionProgress.stories.tsx | |
| +++ b/src/components/common/BulkActionProgress/BulkActionProgress.stories.tsx | |
| @@ -1,5 +1,5 @@ | |
| -import type { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, userEvent, waitFor, within } from "@storybook/test"; | |
| +import type { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, userEvent, waitFor, within } from "storybook/test"; | |
| import { useEffect, useState } from "react"; | |
| import { BulkActionProgress } from "./BulkActionProgress"; | |
| import { BulkActionFeedback } from "./types"; | |
| diff --git a/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx b/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx | |
| index 63cb4fc9f..5889a7156 100644 | |
| --- a/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx | |
| +++ b/src/components/common/EmployeePinInput/EmployeePinInput.stories.tsx | |
| @@ -1,5 +1,5 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, userEvent, waitFor, within } from "@storybook/test"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, fn, userEvent, waitFor, within } from "storybook/test"; | |
| import { useState } from "react"; | |
| import { EmployeePinInput } from "./EmployeePinInput"; | |
| @@ -9,6 +9,12 @@ const meta = { | |
| parameters: { | |
| layout: "centered", | |
| }, | |
| + args: { | |
| + onChange: fn(), | |
| + onComplete: fn(), | |
| + onFocus: fn(), | |
| + onBlur: fn(), | |
| + }, | |
| argTypes: { | |
| value: { | |
| control: { type: "text" }, | |
| @@ -27,11 +33,9 @@ const meta = { | |
| description: "Additional CSS classes to apply", | |
| }, | |
| onChange: { | |
| - action: "changed", | |
| description: "Callback fired when the value changes", | |
| }, | |
| onComplete: { | |
| - action: "completed", | |
| description: "Callback fired when all 4 digits are entered", | |
| }, | |
| }, | |
| diff --git a/src/components/common/LearnMoreAccordion/LearnMoreAccordion.stories.tsx b/src/components/common/LearnMoreAccordion/LearnMoreAccordion.stories.tsx | |
| index 3f997f11d..acafadf54 100644 | |
| --- a/src/components/common/LearnMoreAccordion/LearnMoreAccordion.stories.tsx | |
| +++ b/src/components/common/LearnMoreAccordion/LearnMoreAccordion.stories.tsx | |
| @@ -1,5 +1,5 @@ | |
| -import type { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, userEvent, waitFor, within } from "@storybook/test"; | |
| +import type { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, userEvent, waitFor, within } from "storybook/test"; | |
| import { useState } from "react"; | |
| import { LearnMoreAccordion } from "./LearnMoreAccordion"; | |
| diff --git a/src/components/common/SavingIndicator/SavingIndicator.stories.tsx b/src/components/common/SavingIndicator/SavingIndicator.stories.tsx | |
| index ee6d48c82..8fae2e50f 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-vite"; | |
| import { SavingIndicator } from "./SavingIndicator"; | |
| const meta = { | |
| diff --git a/src/components/common/StyledPaginationControls/StyledPaginationControls.stories.tsx b/src/components/common/StyledPaginationControls/StyledPaginationControls.stories.tsx | |
| index 2c5c185d0..94f7ae28d 100644 | |
| --- a/src/components/common/StyledPaginationControls/StyledPaginationControls.stories.tsx | |
| +++ b/src/components/common/StyledPaginationControls/StyledPaginationControls.stories.tsx | |
| @@ -1,4 +1,4 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| import { MemoryRouter } from "react-router-dom"; | |
| import { StyledPaginationControls } from "./StyledPaginationControls"; | |
| diff --git a/src/components/invoices/__tests__/InvoiceStatusTag.stories.tsx b/src/components/invoices/__tests__/InvoiceStatusTag.stories.tsx | |
| index 3e7623d33..ae7df2264 100644 | |
| --- a/src/components/invoices/__tests__/InvoiceStatusTag.stories.tsx | |
| +++ b/src/components/invoices/__tests__/InvoiceStatusTag.stories.tsx | |
| @@ -1,5 +1,5 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, within } from "@storybook/test"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, within } from "storybook/test"; | |
| import { InvoiceStatus } from "model/data-contracts"; | |
| import { InvoiceStatusTag } from "../InvoiceStatusTag"; | |
| diff --git a/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountCurrentBalance.stories.tsx b/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountCurrentBalance.stories.tsx | |
| index b30cfa8f5..68dd3d2d4 100644 | |
| --- a/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountCurrentBalance.stories.tsx | |
| +++ b/src/components/loyalty/CustomerProfile/HouseAccount/HouseAccountCurrentBalance.stories.tsx | |
| @@ -1,4 +1,4 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| import { HouseAccountCurrentBalance } from "./HouseAccountCurrentBalance"; | |
| const meta = { | |
| diff --git a/src/components/loyalty/CustomerProfile/NewCustomerForm.stories.tsx b/src/components/loyalty/CustomerProfile/NewCustomerForm.stories.tsx | |
| index 0d6d2afd9..390c25c62 100644 | |
| --- a/src/components/loyalty/CustomerProfile/NewCustomerForm.stories.tsx | |
| +++ b/src/components/loyalty/CustomerProfile/NewCustomerForm.stories.tsx | |
| @@ -1,6 +1,6 @@ | |
| import { ChakraProvider } from "@chakra-ui/react"; | |
| -import type { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, fn, userEvent, within } from "@storybook/test"; | |
| +import type { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, fn, userEvent, within } from "storybook/test"; | |
| import { MockEntityProvider } from "src/test/mocks/entityProvider"; | |
| import { NewCustomerForm } from "./NewCustomerForm"; | |
| diff --git a/src/components/po/PurchaseOrderCandidateItems.stories.tsx b/src/components/po/PurchaseOrderCandidateItems.stories.tsx | |
| index ba4c19ff6..4506c12e8 100644 | |
| --- a/src/components/po/PurchaseOrderCandidateItems.stories.tsx | |
| +++ b/src/components/po/PurchaseOrderCandidateItems.stories.tsx | |
| @@ -1,7 +1,7 @@ | |
| import { defaultHandlers } from ".storybook/preview"; | |
| import { ChakraProvider } from "@chakra-ui/react"; | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| -import { expect, userEvent, waitFor, within } from "@storybook/test"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| +import { expect, userEvent, waitFor, within } from "storybook/test"; | |
| import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | |
| import { http, HttpResponse } from "msw"; | |
| import { MemoryRouter } from "react-router-dom"; | |
| diff --git a/src/config/statsigBootstrap.ts b/src/config/statsigBootstrap.ts | |
| index 8f555c945..dd28dad8f 100644 | |
| --- a/src/config/statsigBootstrap.ts | |
| +++ b/src/config/statsigBootstrap.ts | |
| @@ -13,7 +13,10 @@ export type AuditLogPreset = { | |
| }; | |
| // Shared default values for audit log config - used in both Statsig bootstrap and AuditLogsPanelV2.tsx | |
| -export const DEFAULT_AUDIT_LOG_CHANGED_FIELDS: Record<string, { value: string; label: string }[]> = { | |
| +export const DEFAULT_AUDIT_LOG_CHANGED_FIELDS: Record< | |
| + string, | |
| + { value: string; label: string }[] | |
| +> = { | |
| ITEM: [ | |
| { value: "price", label: "Price" }, | |
| { value: "quantity", label: "Quantity" }, | |
| @@ -154,7 +157,9 @@ export const STATSIG_BOOTSTRAP_VALUES = { | |
| }, | |
| }, | |
| }, | |
| - feature_gates: {}, | |
| + feature_gates: { | |
| + department_entity_tax: true, | |
| + }, | |
| layer_configs: {}, | |
| has_updates: true, | |
| time: Date.now(), | |
| diff --git a/src/context/DepartmentContext.tsx b/src/context/DepartmentContext.tsx | |
| index 074166bb6..6c6fc675c 100644 | |
| --- a/src/context/DepartmentContext.tsx | |
| +++ b/src/context/DepartmentContext.tsx | |
| @@ -19,10 +19,12 @@ import { | |
| DepartmentGroup, | |
| listDepartmentGroupsQueryOptions, | |
| listDepartmentsQueryOptions, | |
| + ListDepartmentsQueryParams, | |
| } from "src/spring-generated"; | |
| import { mapPgLiteQueryFn, useAutoOfflineQuery } from "utils/offlineUtils"; | |
| import { useCohortIdProvider } from "./CohortProvider"; | |
| import { useEntity } from "./EntityProvider"; | |
| +import { useFeatureFlagCallback } from "hooks/usePostHogFeatureFlag"; | |
| /** | |
| * Maps PGLite department data to API format | |
| @@ -61,9 +63,23 @@ const useGetAllDepartmentsForEntityInternal = () => { | |
| const queryClient = useQueryClient(); | |
| const pgLiteDb = usePGliteOptional(); | |
| + const { checkGate } = useFeatureFlagCallback({ | |
| + flag: "department_entity_tax", | |
| + defaultValue: false, | |
| + }); | |
| + | |
| + const listDepartmentsQueryParams: ListDepartmentsQueryParams = useMemo(() => { | |
| + return { | |
| + entityId: entity?.id ?? 0, | |
| + featureFlags: [checkGate() ? "department_entity_tax" : undefined].filter( | |
| + (f) => f !== undefined, | |
| + ), | |
| + }; | |
| + }, [entity?.id, checkGate]); | |
| + | |
| const { data, isFetching, queryKey } = useAutoOfflineQuery( | |
| { | |
| - ...listDepartmentsQueryOptions(), | |
| + ...listDepartmentsQueryOptions(listDepartmentsQueryParams), | |
| enabled: !!entity?.cohortId, | |
| refetchOnWindowFocus: false, | |
| refetchOnMount: false, | |
| diff --git a/src/pages/NotFoundPage.stories.tsx b/src/pages/NotFoundPage.stories.tsx | |
| index c0922567c..93705d848 100644 | |
| --- a/src/pages/NotFoundPage.stories.tsx | |
| +++ b/src/pages/NotFoundPage.stories.tsx | |
| @@ -1,4 +1,4 @@ | |
| -import { Meta, StoryObj } from "@storybook/react"; | |
| +import { Meta, StoryObj } from "@storybook/react-vite"; | |
| import { MemoryRouter } from "react-router-dom"; | |
| import { QueryParamProvider } from "use-query-params"; | |
| import { ReactRouter6Adapter } from "use-query-params/adapters/react-router-6"; | |
| diff --git a/src/pages/TransactionPage.tsx b/src/pages/TransactionPage.tsx | |
| index e144d58ce..f3a1ee62a 100644 | |
| --- a/src/pages/TransactionPage.tsx | |
| +++ b/src/pages/TransactionPage.tsx | |
| @@ -76,6 +76,7 @@ import { | |
| } from "src/spring-generated"; | |
| import { FinishTransacationPaymentModal } from "../components/TransactionsComponents/FinishTransactionPaymentModal"; | |
| import { useTransactionReceipt } from "../components/TransactionsComponents/useTransactionReceipt"; | |
| +import { extractAxios400ErrorMessage } from "utils/errors"; | |
| const CANCELABLE_TRANSACTION_STATUS = new Set([ | |
| TransactionStatus.CREATED, | |
| @@ -233,7 +234,7 @@ const TransactionPage = () => { | |
| onError: (err: any) => { | |
| toast({ | |
| title: "Error", | |
| - description: err.response?.data?.message, | |
| + description: extractAxios400ErrorMessage(err), | |
| variant: "destructive", | |
| }); | |
| captureException(err); | |
| @@ -610,7 +611,11 @@ const TransactionPage = () => { | |
| variant="destructive" | |
| onClick={async () => { | |
| if (!txId) return; | |
| - await deleteTransaction({} as never); | |
| + try { | |
| + await deleteTransaction({} as never); | |
| + } catch { | |
| + // Error handled in onError callback | |
| + } | |
| }} | |
| > | |
| <Button | |
| diff --git a/src/pages/inventory/InventoryCountInputPage.tsx b/src/pages/inventory/InventoryCountInputPage.tsx | |
| index 4f3e970f4..07c86b746 100644 | |
| --- a/src/pages/inventory/InventoryCountInputPage.tsx | |
| +++ b/src/pages/inventory/InventoryCountInputPage.tsx | |
| @@ -50,7 +50,13 @@ export type AddForm = { | |
| const columnHelper = createColumnHelper<InventoryCountItemOutput>(); | |
| -export const DeleteInventoryCountItemButton = ({ id }: { id: number }) => { | |
| +export const DeleteInventoryCountItemButton = ({ | |
| + id, | |
| + disabled, | |
| +}: { | |
| + id: number; | |
| + disabled?: boolean; | |
| +}) => { | |
| const queryClient = useQueryClient(); | |
| const { mutateAsync: deleteItem, isPending } = | |
| @@ -70,6 +76,7 @@ export const DeleteInventoryCountItemButton = ({ id }: { id: number }) => { | |
| colorScheme="red" | |
| icon={<DeleteIcon />} | |
| isLoading={isPending} | |
| + isDisabled={disabled} | |
| onClick={() => deleteItem({} as never)} | |
| ></IconButton> | |
| ); | |
| @@ -111,6 +118,12 @@ export const InventoryCountInputPage: React.FC< | |
| const countInputRef = useRef<HTMLInputElement>(null); | |
| const toast = useToast(); | |
| + const inventoryCount = useGetInventoryCountById(id, { | |
| + zoneId: Intl.DateTimeFormat().resolvedOptions().timeZone, | |
| + }); | |
| + | |
| + const isCompleted = inventoryCount.data?.result.status === "COMPLETE"; | |
| + | |
| const { data, isLoading, queryKey } = useGetInventoryCountItemsById( | |
| id, | |
| { | |
| @@ -240,18 +253,19 @@ export const InventoryCountInputPage: React.FC< | |
| columnHelper.display({ | |
| header: " ", | |
| cell: ({ row }) => ( | |
| - <DeleteInventoryCountItemButton id={row.original.id} /> | |
| + <DeleteInventoryCountItemButton | |
| + id={row.original.id} | |
| + disabled={isCompleted} | |
| + /> | |
| ), | |
| }), | |
| ]; | |
| - }, []); | |
| - | |
| - const d = useGetInventoryCountById(id, { | |
| - zoneId: "", | |
| - }); | |
| + }, [isCompleted]); | |
| useDocumentTitle( | |
| - d.data ? `Inventory Count: ${d.data.result.name}` : undefined, | |
| + inventoryCount.data | |
| + ? `Inventory Count: ${inventoryCount.data.result.name}` | |
| + : undefined, | |
| ); | |
| return ( | |
| @@ -259,8 +273,8 @@ export const InventoryCountInputPage: React.FC< | |
| <CardHeader> | |
| <HStack w="100%" justifyContent="space-between"> | |
| <HStack> | |
| - <Heading size="md">{d.data?.result.name}</Heading> | |
| - <Spinner hidden={!isLoading || !d.isLoading} /> | |
| + <Heading size="md">{inventoryCount.data?.result.name}</Heading> | |
| + <Spinner hidden={!isLoading || !inventoryCount.isLoading} /> | |
| </HStack> | |
| </HStack> | |
| </CardHeader> | |
| @@ -290,6 +304,7 @@ export const InventoryCountInputPage: React.FC< | |
| countInputRef.current?.focus(); | |
| countInputRef.current?.select(); | |
| }} | |
| + isDisabled={isCompleted} | |
| /> | |
| )} | |
| /> | |
| @@ -309,6 +324,7 @@ export const InventoryCountInputPage: React.FC< | |
| onValueChange={(value) => { | |
| field.onChange(value); | |
| }} | |
| + disabled={isCompleted} | |
| /> | |
| )} | |
| /> | |
| @@ -317,7 +333,7 @@ export const InventoryCountInputPage: React.FC< | |
| requires="inventory_count/*:count" | |
| type="submit" | |
| isLoading={isPending} | |
| - disabled={isPending} | |
| + disabled={isPending || isCompleted} | |
| leftIcon={<AddIcon />} | |
| > | |
| Add | |
| @@ -337,6 +353,7 @@ export const InventoryCountInputPage: React.FC< | |
| } | |
| setSearchState(val); | |
| }} | |
| + disabled={isCompleted} | |
| /> | |
| <TransformityDataTable | |
| variant="pretty" | |
| diff --git a/src/test/mocks/MockPointerEvent.ts b/src/test/mocks/MockPointerEvent.ts | |
| index 2972bf335..7498c294d 100644 | |
| --- a/src/test/mocks/MockPointerEvent.ts | |
| +++ b/src/test/mocks/MockPointerEvent.ts | |
| @@ -1,4 +1,4 @@ | |
| -import { fn } from "@storybook/test"; | |
| +import { fn } from "storybook/test"; | |
| export class MockPointerEvent extends Event { | |
| button: number; | |
| diff --git a/stably.yaml b/stably.yaml | |
| new file mode 100644 | |
| index 000000000..2824af685 | |
| --- /dev/null | |
| +++ b/stably.yaml | |
| @@ -0,0 +1,27 @@ | |
| +# Stably Configuration | |
| +# Scheduled test runs for production, beta, and gamma environments | |
| + | |
| +schedules: | |
| + production-every-30min: | |
| + cron: "*/30 * * * *" | |
| + stablyTestArgs: "--project chromium" | |
| + env: | |
| + TEST_BASE_URL: "https://pos.transformity.tech" | |
| + | |
| + beta-every-30min: | |
| + cron: "*/30 * * * *" | |
| + stablyTestArgs: "--project chromium" | |
| + env: | |
| + TEST_BASE_URL: "https://pos.beta.transformity.tech" | |
| + | |
| + gamma-every-30min: | |
| + cron: "*/30 * * * *" | |
| + stablyTestArgs: "--project chromium" | |
| + env: | |
| + TEST_BASE_URL: "https://dev.pos.transformity.tech" | |
| + | |
| +notifications: | |
| + email: | |
| + onFailure: true | |
| + recipients: | |
| + - issue@transformity.pagerduty.com | |
| diff --git a/vite.config.ts b/vite.config.ts | |
| index bfb58f36f..d4a480962 100644 | |
| --- a/vite.config.ts | |
| +++ b/vite.config.ts | |
| @@ -120,4 +120,8 @@ export default defineConfig({ | |
| ignored: ["**/node_modules/**", "**/dist/**", "**/.git/**"], | |
| }, | |
| }, | |
| + preview: { | |
| + host: "localhost", | |
| + port: 3000, | |
| + }, | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment