@autobusal/providers 1.46.1 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,7 @@
1
- import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
1
+ import { QueryClientProvider, QueryClient, MutationCache } from '@tanstack/react-query';
2
2
  import { AxiosError } from 'axios';
3
+ import i18next from 'i18next';
4
+ import { error as systemError } from '@autobusal/utilities';
3
5
 
4
6
  /**
5
7
  * Edited: Ferjolt Ozuni - Date: 2026-08-06
@@ -45,7 +47,42 @@ const retry = (failureCount: number, error: Error): boolean => {
45
47
  // an unbounded exponential backoff reaches.
46
48
  const retryDelay = (attempt: number): number => 700 * 2 ** attempt;
47
49
 
50
+ /*
51
+ * Claude - 2026-11-03 (dashboard simplification, wave 0).
52
+ *
53
+ * A failed SAVE always says so. The API client toasts a 422 and a 500 and
54
+ * sends a 401 to the login page, and every other answer to a mutation - a
55
+ * 403 that is not the documents gate, a 404, a 409, a 429, a connection that
56
+ * dropped mid-request - was shown by nobody unless the screen remembered to
57
+ * pass its own onError, which a handful did and the rest did not: the brand
58
+ * list's save "did nothing" on a 403 for weeks.
59
+ *
60
+ * Mutations only. A query that fails has the page's own loading state and
61
+ * the retry policy above; a mutation is an action somebody just took and is
62
+ * waiting to hear about.
63
+ */
64
+ const HANDLED = [ 401, 422, 500 ];
65
+
66
+ const mutationCache = new MutationCache({
67
+ onError: (error) => {
68
+ const response = (error as AxiosError<{ message?: string, reason?: string }>)?.response;
69
+
70
+ if (response === undefined) {
71
+ systemError(i18next.t('errors.network', { ns: 'common', defaultValue: 'The connection was lost. Please try again.' }));
72
+
73
+ return;
74
+ }
75
+
76
+ if (HANDLED.includes(response.status) || (response.status === 403 && response.data?.reason === 'documents')) {
77
+ return;
78
+ }
79
+
80
+ systemError(response.data?.message ?? i18next.t('errors.server', { ns: 'common', defaultValue: 'Something went wrong. Please try again.' }));
81
+ }
82
+ });
83
+
48
84
  const queryClient = new QueryClient({
85
+ mutationCache,
49
86
  defaultOptions: {
50
87
  queries: {
51
88
  refetchOnWindowFocus: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/providers",
3
- "version": "1.46.1",
3
+ "version": "1.47.0",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -0,0 +1,28 @@
1
+ /**
2
+ * One brand's fiscalisation state - GET /api/label/admin/fiscal (its own
3
+ * brand) and the System page's list of every brand (GET /api/system/admin).
4
+ *
5
+ * Claude - 2026-11-04 (dashboard simplification, wave 7; plan D25): it was
6
+ * declared twice, in admin-label and admin-system, and the two had already
7
+ * drifted (one typed `blocker` as a string, the other as the closed list).
8
+ */
9
+ export interface FiscalStatus {
10
+ label: { id: number, name: string }
11
+ mode: string | null
12
+ url: string | null
13
+ owner: { id: number, email: string } | null
14
+ account: {
15
+ enabled: boolean
16
+ exists: boolean
17
+ missing: string[]
18
+ token: boolean
19
+ token_expires: string | null
20
+ cash_register: boolean
21
+ fiscalization_number: boolean
22
+ reason: string | null
23
+ }
24
+ blocker: 'label_unconfigured' | 'no_owner' | 'no_account' | 'account_incomplete' | 'disabled' | 'no_token' | 'token_expired' | 'no_cash_register' | null
25
+ orders: { sold: number, late: number, sent_7d: number }
26
+ last_error: { order_id: number, status: number, message: string, at: string | null } | null
27
+ last_success: string | null
28
+ }
package/types/theme.ts ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The tokens every styled component reads from `props.theme`.
3
+ *
4
+ * Claude - 2026-11-04 (dashboard simplification, wave 6, D26). Styles.tsx
5
+ * hands styled-components `{ ...colors[mode], ...theme }` from the label's
6
+ * settings, and obtapi floors every label's colours onto
7
+ * resources/themes/default-settings.json (Labels\ThemeColors), so this is
8
+ * that file's shape. An app declares `DefaultTheme extends ThemeTokens`
9
+ * (magus src/styled.d.ts) and a token nothing defines - `size.info`,
10
+ * `font.neutral`, which silently dropped their CSS - stops compiling.
11
+ */
12
+ export interface ThemeTokens {
13
+ font: {
14
+ normal: string
15
+ faded: string
16
+ success: string
17
+ error: string
18
+ warning: string
19
+ info: string
20
+ }
21
+
22
+ background: {
23
+ normal: string
24
+ neutral: string
25
+ box: string
26
+ }
27
+
28
+ foreground: {
29
+ normal: string
30
+ }
31
+
32
+ header: {
33
+ font: string
34
+ background: string
35
+ transparent: string
36
+ }
37
+
38
+ menu: {
39
+ font: string
40
+ background: string
41
+ transparent: string
42
+ hover: string
43
+ }
44
+
45
+ submenu: {
46
+ font: string
47
+ background: string
48
+ transparent: string
49
+ hover: string
50
+ }
51
+
52
+ footer: {
53
+ font: string
54
+ background: string
55
+ }
56
+
57
+ inputs: {
58
+ font: string
59
+ background: string
60
+ border: string
61
+ }
62
+
63
+ primary: {
64
+ normal: string
65
+ neutral: string
66
+ contrast: string
67
+ }
68
+
69
+ boxShadow: string
70
+
71
+ fontFamily: {
72
+ title: string
73
+ content: string
74
+ }
75
+
76
+ size: {
77
+ xxl: string
78
+ xl: string
79
+ l: string
80
+ m: string
81
+ s: string
82
+ xs: string
83
+ xxs: string
84
+ }
85
+
86
+ lineHeight: {
87
+ title: number | string
88
+ content: number | string
89
+ }
90
+
91
+ borderRadius: string
92
+ }