@licklist/design 0.78.5-dev.60 → 0.78.5-dev.63

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.
Files changed (94) hide show
  1. package/dist/auth/Login/LoginPage.d.ts +8 -0
  2. package/dist/auth/Login/LoginPage.d.ts.map +1 -0
  3. package/dist/auth/Login/LoginPage.js +206 -0
  4. package/dist/auth/Login/index.d.ts +1 -0
  5. package/dist/auth/Login/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/v2/components/ActionMenu/ActionMenu.d.ts.map +1 -1
  8. package/dist/v2/components/ActionMenu/ActionMenu.js +6 -16
  9. package/dist/v2/components/ActionMenu/ActionMenu.scss.js +1 -1
  10. package/dist/v2/components/FormField/FormField.d.ts +2 -0
  11. package/dist/v2/components/FormField/FormField.d.ts.map +1 -1
  12. package/dist/v2/components/FormField/FormField.js +12 -3
  13. package/dist/v2/components/FormField/FormField.scss.js +1 -1
  14. package/dist/v2/components/NewPageHeader/NewPageHeader.scss.js +1 -1
  15. package/dist/v2/components/ZoneCard/ResourceRow.d.ts +11 -0
  16. package/dist/v2/components/ZoneCard/ResourceRow.d.ts.map +1 -1
  17. package/dist/v2/components/ZoneCard/ResourceRow.js +61 -9
  18. package/dist/v2/components/ZoneCard/ZoneCard.d.ts +0 -1
  19. package/dist/v2/components/ZoneCard/ZoneCard.d.ts.map +1 -1
  20. package/dist/v2/components/ZoneCard/ZoneCard.js +1 -2
  21. package/dist/v2/components/ZoneCard/ZoneCard.scss.js +1 -1
  22. package/dist/v2/components/ZoneCard/ZoneHeader.d.ts +6 -1
  23. package/dist/v2/components/ZoneCard/ZoneHeader.d.ts.map +1 -1
  24. package/dist/v2/components/ZoneCard/ZoneHeader.js +30 -13
  25. package/dist/v2/components/ZoneCard/index.d.ts +1 -1
  26. package/dist/v2/components/ZoneCard/index.d.ts.map +1 -1
  27. package/dist/v2/icons/index.d.ts +18 -2
  28. package/dist/v2/icons/index.d.ts.map +1 -1
  29. package/dist/v2/icons/index.js +21 -41
  30. package/dist/v2/index.d.ts +3 -1
  31. package/dist/v2/index.d.ts.map +1 -1
  32. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.d.ts.map +1 -1
  33. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.js +20 -16
  34. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.scss.js +1 -1
  35. package/dist/v2/pages/auth/AuthLayout/AuthLayout.d.ts +14 -0
  36. package/dist/v2/pages/auth/AuthLayout/AuthLayout.d.ts.map +1 -0
  37. package/dist/v2/pages/auth/AuthLayout/index.d.ts +3 -0
  38. package/dist/v2/pages/auth/AuthLayout/index.d.ts.map +1 -0
  39. package/dist/v2/pages/auth/CreatePassword/CreatePasswordPage.d.ts +10 -0
  40. package/dist/v2/pages/auth/CreatePassword/CreatePasswordPage.d.ts.map +1 -0
  41. package/dist/v2/pages/auth/CreatePassword/index.d.ts +3 -0
  42. package/dist/v2/pages/auth/CreatePassword/index.d.ts.map +1 -0
  43. package/dist/v2/pages/auth/Login/LoginPage.d.ts +11 -0
  44. package/dist/v2/pages/auth/Login/LoginPage.d.ts.map +1 -0
  45. package/dist/v2/pages/auth/Login/index.d.ts +3 -0
  46. package/dist/v2/pages/auth/Login/index.d.ts.map +1 -0
  47. package/dist/v2/pages/auth/ResetPassword/ResetPasswordPage.d.ts +12 -0
  48. package/dist/v2/pages/auth/ResetPassword/ResetPasswordPage.d.ts.map +1 -0
  49. package/dist/v2/pages/auth/ResetPassword/index.d.ts +3 -0
  50. package/dist/v2/pages/auth/ResetPassword/index.d.ts.map +1 -0
  51. package/dist/v2/pages/auth/VerifyEmail/VerifyEmailPage.d.ts +9 -0
  52. package/dist/v2/pages/auth/VerifyEmail/VerifyEmailPage.d.ts.map +1 -0
  53. package/dist/v2/pages/auth/VerifyEmail/index.d.ts +3 -0
  54. package/dist/v2/pages/auth/VerifyEmail/index.d.ts.map +1 -0
  55. package/dist/v2/pages/auth/index.d.ts +11 -0
  56. package/dist/v2/pages/auth/index.d.ts.map +1 -0
  57. package/package.json +2 -2
  58. package/src/auth/Login/LoginPage.tsx +52 -0
  59. package/src/auth/Login/index.ts +1 -0
  60. package/src/v2/components/ActionMenu/ActionMenu.scss +7 -20
  61. package/src/v2/components/ActionMenu/ActionMenu.tsx +2 -5
  62. package/src/v2/components/FormField/FormField.scss +9 -1
  63. package/src/v2/components/FormField/FormField.tsx +31 -19
  64. package/src/v2/components/NewPageHeader/NewPageHeader.scss +1 -5
  65. package/src/v2/components/ZoneCard/ResourceRow.tsx +56 -9
  66. package/src/v2/components/ZoneCard/ZoneCard.scss +74 -10
  67. package/src/v2/components/ZoneCard/ZoneCard.stories.tsx +2 -5
  68. package/src/v2/components/ZoneCard/ZoneCard.tsx +0 -3
  69. package/src/v2/components/ZoneCard/ZoneHeader.tsx +34 -11
  70. package/src/v2/components/ZoneCard/index.ts +1 -1
  71. package/src/v2/icons/index.tsx +113 -16
  72. package/src/v2/index.ts +5 -1
  73. package/src/v2/pages/ZonesResources/ZonesResourcesPage.scss +25 -0
  74. package/src/v2/pages/ZonesResources/ZonesResourcesPage.tsx +10 -7
  75. package/src/v2/pages/auth/AuthLayout/AuthLayout.scss +135 -0
  76. package/src/v2/pages/auth/AuthLayout/AuthLayout.tsx +61 -0
  77. package/src/v2/pages/auth/AuthLayout/index.ts +2 -0
  78. package/src/v2/pages/auth/CreatePassword/CreatePasswordPage.scss +149 -0
  79. package/src/v2/pages/auth/CreatePassword/CreatePasswordPage.stories.tsx +45 -0
  80. package/src/v2/pages/auth/CreatePassword/CreatePasswordPage.tsx +181 -0
  81. package/src/v2/pages/auth/CreatePassword/index.ts +2 -0
  82. package/src/v2/pages/auth/Login/LoginPage.scss +49 -0
  83. package/src/v2/pages/auth/Login/LoginPage.stories.tsx +45 -0
  84. package/src/v2/pages/auth/Login/LoginPage.tsx +100 -0
  85. package/src/v2/pages/auth/Login/index.ts +2 -0
  86. package/src/v2/pages/auth/ResetPassword/ResetPasswordPage.scss +82 -0
  87. package/src/v2/pages/auth/ResetPassword/ResetPasswordPage.stories.tsx +53 -0
  88. package/src/v2/pages/auth/ResetPassword/ResetPasswordPage.tsx +110 -0
  89. package/src/v2/pages/auth/ResetPassword/index.ts +2 -0
  90. package/src/v2/pages/auth/VerifyEmail/VerifyEmailPage.scss +72 -0
  91. package/src/v2/pages/auth/VerifyEmail/VerifyEmailPage.stories.tsx +41 -0
  92. package/src/v2/pages/auth/VerifyEmail/VerifyEmailPage.tsx +110 -0
  93. package/src/v2/pages/auth/VerifyEmail/index.ts +2 -0
  94. package/src/v2/pages/auth/index.ts +14 -0
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import './CreatePasswordPage.scss';
3
+ export interface CreatePasswordPageProps {
4
+ onSubmit: (password: string) => Promise<void> | void;
5
+ onResetInstead?: () => void;
6
+ isLoading?: boolean;
7
+ error?: string;
8
+ }
9
+ export declare const CreatePasswordPage: React.FC<CreatePasswordPageProps>;
10
+ //# sourceMappingURL=CreatePasswordPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreatePasswordPage.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/CreatePassword/CreatePasswordPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,2BAA2B,CAAA;AAOlC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACpD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA+JhE,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { CreatePasswordPage } from './CreatePasswordPage';
2
+ export type { CreatePasswordPageProps } from './CreatePasswordPage';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/CreatePassword/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import './LoginPage.scss';
3
+ export interface LoginPageProps {
4
+ onSubmit: (email: string, password: string) => Promise<void> | void;
5
+ onForgotPassword?: () => void;
6
+ isLoading?: boolean;
7
+ error?: string;
8
+ version?: string;
9
+ }
10
+ export declare const LoginPage: React.FC<LoginPageProps>;
11
+ //# sourceMappingURL=LoginPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginPage.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/Login/LoginPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,kBAAkB,CAAA;AAOzB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACnE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA4E9C,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { LoginPage } from './LoginPage';
2
+ export type { LoginPageProps } from './LoginPage';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/Login/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import './ResetPasswordPage.scss';
3
+ export interface ResetPasswordPageProps {
4
+ onSubmit: (email: string) => Promise<void> | void;
5
+ onBackToLogin?: () => void;
6
+ isLoading?: boolean;
7
+ error?: string;
8
+ successMessage?: string;
9
+ version?: string;
10
+ }
11
+ export declare const ResetPasswordPage: React.FC<ResetPasswordPageProps>;
12
+ //# sourceMappingURL=ResetPasswordPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResetPasswordPage.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/ResetPassword/ResetPasswordPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,0BAA0B,CAAA;AAMjC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACjD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAsF9D,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { ResetPasswordPage } from './ResetPasswordPage';
2
+ export type { ResetPasswordPageProps } from './ResetPasswordPage';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/ResetPassword/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import './VerifyEmailPage.scss';
3
+ export interface VerifyEmailPageProps {
4
+ onSubmit: (code: string) => Promise<void> | void;
5
+ isLoading?: boolean;
6
+ error?: string;
7
+ }
8
+ export declare const VerifyEmailPage: React.FC<VerifyEmailPageProps>;
9
+ //# sourceMappingURL=VerifyEmailPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VerifyEmailPage.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/VerifyEmail/VerifyEmailPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2B,MAAM,OAAO,CAAA;AAK/C,OAAO,wBAAwB,CAAA;AAI/B,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA8F1D,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { VerifyEmailPage } from './VerifyEmailPage';
2
+ export type { VerifyEmailPageProps } from './VerifyEmailPage';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/v2/pages/auth/VerifyEmail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,11 @@
1
+ export { AuthLayout } from './AuthLayout';
2
+ export type { AuthLayoutProps } from './AuthLayout';
3
+ export { LoginPage } from './Login';
4
+ export type { LoginPageProps } from './Login';
5
+ export { ResetPasswordPage } from './ResetPassword';
6
+ export type { ResetPasswordPageProps } from './ResetPassword';
7
+ export { CreatePasswordPage } from './CreatePassword';
8
+ export type { CreatePasswordPageProps } from './CreatePassword';
9
+ export { VerifyEmailPage } from './VerifyEmail';
10
+ export type { VerifyEmailPageProps } from './VerifyEmail';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/pages/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,YAAY,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@licklist/design",
3
- "version": "0.78.5-dev.60",
3
+ "version": "0.78.5-dev.63",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+ssh://git@bitbucket.org/bookedit-licklist/licklist_design.git"
@@ -42,7 +42,7 @@
42
42
  ]
43
43
  },
44
44
  "peerDependencies": {
45
- "@licklist/core": "0.36.1-dev.14",
45
+ "@licklist/core": "0.36.1-dev.17-new",
46
46
  "@licklist/eslint-config": "0.5.6",
47
47
  "@licklist/plugins": "0.36.4-dev.13",
48
48
  "clsx": "2.1.1",
@@ -0,0 +1,52 @@
1
+ import { useEffect } from 'react'
2
+ import Row from 'react-bootstrap/Row'
3
+ import Col from 'react-bootstrap/Col'
4
+ import { useTranslation } from 'react-i18next'
5
+ import useAlert from '@licklist/plugins/dist/context/app/hooks/useAlert'
6
+ import FormCard from '../../static/FormCard'
7
+ import Logo from '../../logo/Logo'
8
+ import { ReactComponent as BookeditLogoSvg } from '../../assets/logo/bookedit.svg'
9
+ import { LoginFormComponent } from './LoginFormComponent'
10
+
11
+ export interface LoginPageProps {
12
+ onSubmit: (email: string, password: string) => void | Promise<void>
13
+ onForgotPassword?: () => void
14
+ isLoading?: boolean
15
+ error?: string
16
+ }
17
+
18
+ export const LoginPage = ({ onSubmit, isLoading = false, error }: LoginPageProps) => {
19
+ const { t } = useTranslation(['User'])
20
+ const { showAlert } = useAlert()
21
+
22
+ useEffect(() => {
23
+ if (error) {
24
+ showAlert({ type: 'error', message: error })
25
+ }
26
+ }, [error])
27
+
28
+ const handleSubmit = async (credentials: { email: string; password: string }) => {
29
+ await onSubmit(credentials.email, credentials.password)
30
+ }
31
+
32
+ return (
33
+ <Row className='justify-content-center'>
34
+ <Col xs sm={12} md={7} lg={6} xl={5} className='align-self-center'>
35
+ <h1 className='text-center'>{t('User:loginTitle')}</h1>
36
+
37
+ <div className='login d-flex pb-4 justify-content-center'>
38
+ <Logo logo={<BookeditLogoSvg />} />
39
+ </div>
40
+
41
+ <FormCard>
42
+ <LoginFormComponent
43
+ isLoading={isLoading}
44
+ setIsLoading={() => {}}
45
+ onSubmit={handleSubmit}
46
+ invitation={null}
47
+ />
48
+ </FormCard>
49
+ </Col>
50
+ </Row>
51
+ )
52
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './LoginComponent'
2
2
  export * from './LoginFormComponent'
3
+ export * from './LoginPage'
@@ -7,46 +7,33 @@
7
7
 
8
8
  &__trigger {
9
9
  display: flex;
10
- width: 40px;
11
- height: 40px;
12
- padding: 8px;
10
+ width: 32px;
11
+ height: 32px;
12
+ padding: 0;
13
13
  justify-content: center;
14
14
  align-items: center;
15
15
  border-radius: 50%;
16
- border: 1px solid var(--border-primary, #E8E9EF);
16
+ border: none;
17
17
  background: var(--surface-action-soft);
18
18
  color: var(--actions-regular, #5D5BF4);
19
19
  cursor: pointer;
20
20
  transition: all 0.2s ease;
21
+ position: relative;
21
22
 
22
23
  &:hover {
23
- background: var(--surface-action-soft);
24
+ opacity: 0.8;
24
25
  }
25
26
 
26
27
  &--close {
27
28
  border-radius: 50%;
28
29
  background: #F4F4FE;
29
- border: 1px solid #F4F4FE;
30
30
 
31
31
  &:hover {
32
32
  background: #E8E8FD;
33
+ opacity: 1;
33
34
  }
34
35
  }
35
36
 
36
- svg {
37
- width: 28px;
38
- height: 28px;
39
- }
40
-
41
- .action-menu__circle {
42
- position: absolute;
43
- top: 50%;
44
- left: 50%;
45
- transform: translate(-50%, -50%);
46
- width: 32px;
47
- height: 32px;
48
- z-index: -1;
49
- }
50
37
  }
51
38
 
52
39
  &__dropdown {
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useRef, useEffect, useLayoutEffect } from 'react'
2
- import { CloseIcon, EllipsisIcon, CircleIcon } from '../../icons'
2
+ import { CloseIcon, EllipsisIcon } from '../../icons'
3
3
  import './ActionMenu.scss'
4
4
 
5
5
  export interface ActionMenuItem {
@@ -83,10 +83,7 @@ export const ActionMenu: React.FC<ActionMenuProps> = ({ items, className = '', i
83
83
  {isOpen ? (
84
84
  <CloseIcon width={18} height={18} />
85
85
  ) : (
86
- <>
87
- <CircleIcon width={32} height={32} className="action-menu__circle" fill="var(--surface-action-soft)" />
88
- <EllipsisIcon width={18} height={18} fill="var(--fill-action)" />
89
- </>
86
+ <EllipsisIcon width={18} height={4} fill="var(--fill-action)" />
90
87
  )}
91
88
  </button>
92
89
 
@@ -33,7 +33,7 @@
33
33
  padding: 8px 10px;
34
34
  height: 40px;
35
35
  font-family: var(--font-family-sans, 'Geist', sans-serif);
36
- font-size: var(--text-regular-size, 15px);
36
+ font-size: var(--text-regular-size, 16px);
37
37
  line-height: var(--text-regular-line, 20px);
38
38
  color: var(--label-primary, #121e52);
39
39
  background-color: var(--surface-secondary, #f8f8fa);
@@ -60,6 +60,14 @@
60
60
  }
61
61
  }
62
62
 
63
+ &--success {
64
+ border-color: var(--border-status-success, #c9ecbd);
65
+
66
+ &:focus {
67
+ border-color: var(--border-status-success, #c9ecbd);
68
+ }
69
+ }
70
+
63
71
  &:disabled {
64
72
  background: var(--surface-status-disabled, #f8f8fa);
65
73
  color: var(--label-secondary, #626a90);
@@ -4,30 +4,42 @@ import './FormField.scss'
4
4
  export interface FormFieldProps extends InputHTMLAttributes<HTMLInputElement> {
5
5
  label?: string
6
6
  error?: string
7
+ hasError?: boolean
8
+ success?: boolean
7
9
  helpText?: string
8
10
  required?: boolean
9
11
  }
10
12
 
11
13
  export const FormField = forwardRef<HTMLInputElement, FormFieldProps>(
12
- ({ label, error, helpText, required, className = '', ...props }, ref) => (
13
- <div className={`form-field ${className}`}>
14
- {label && (
15
- <label className="form-field__label">
16
- {label}
17
- {required && <span className="form-field__required">*</span>}
18
- </label>
19
- )}
20
- <input
21
- ref={ref}
22
- className={`form-field__input ${error ? 'form-field__input--error' : ''}`}
23
- {...props}
24
- />
25
- {helpText && !error && (
26
- <span className="form-field__help-text">{helpText}</span>
27
- )}
28
- {error && <span className="form-field__error-text">{error}</span>}
29
- </div>
30
- )
14
+ ({ label, error, hasError, success, helpText, required, className = '', ...props }, ref) => {
15
+ const showError = error || hasError
16
+ const showSuccess = success && !showError
17
+ const inputClassName = [
18
+ 'form-field__input',
19
+ showError ? 'form-field__input--error' : '',
20
+ showSuccess ? 'form-field__input--success' : '',
21
+ ].filter(Boolean).join(' ')
22
+
23
+ return (
24
+ <div className={`form-field ${className}`}>
25
+ {label && (
26
+ <label className="form-field__label">
27
+ {label}
28
+ {required && <span className="form-field__required">*</span>}
29
+ </label>
30
+ )}
31
+ <input
32
+ ref={ref}
33
+ className={inputClassName}
34
+ {...props}
35
+ />
36
+ {helpText && !showError && (
37
+ <span className="form-field__help-text">{helpText}</span>
38
+ )}
39
+ {error && <span className="form-field__error-text">{error}</span>}
40
+ </div>
41
+ )
42
+ }
31
43
  )
32
44
 
33
45
  FormField.displayName = 'FormField'
@@ -7,13 +7,9 @@
7
7
  padding: 32px 32px 0px 32px;
8
8
 
9
9
  @media (max-width: 768px) {
10
- padding: 16px 16px 0px 16px;
10
+ padding: 16px 0 0 0;
11
11
  gap: 0;
12
12
  }
13
-
14
- @media (max-width: 480px) {
15
- padding: 16px 12px 0px 12px;
16
- }
17
13
  }
18
14
 
19
15
  .new-page-header {
@@ -1,57 +1,104 @@
1
1
  import React from 'react'
2
2
  import { ActionMenu, ActionMenuItem } from '../ActionMenu'
3
- import { GripVerticalIcon } from '../../icons'
3
+ import { GripVerticalIcon, ArrowUpIcon, ArrowDownIcon } from '../../icons'
4
4
  import { DragHandleProps } from './ZoneContainer'
5
5
  import './ZoneCard.scss'
6
6
 
7
+ export interface ResourceRowLabels {
8
+ quantity?: string
9
+ capacity?: string
10
+ total?: string
11
+ }
12
+
7
13
  export interface ResourceRowProps {
8
14
  name: string
9
15
  quantity: number
10
16
  capacity: number
17
+ labels?: ResourceRowLabels
11
18
  menuItems?: ActionMenuItem[]
12
19
  draggable?: boolean
13
20
  dragHandleProps?: DragHandleProps
14
21
  onClick?: () => void
15
22
  className?: string
16
23
  style?: React.CSSProperties
24
+ isMobile?: boolean
25
+ isFirst?: boolean
26
+ isLast?: boolean
27
+ onMoveUp?: () => void
28
+ onMoveDown?: () => void
17
29
  }
18
30
 
19
31
  export const ResourceRow = React.forwardRef<HTMLDivElement, ResourceRowProps>(({
20
32
  name,
21
33
  quantity,
22
34
  capacity,
35
+ labels = {},
23
36
  menuItems = [],
24
37
  draggable = true,
25
38
  dragHandleProps,
26
39
  onClick,
27
40
  className = '',
28
41
  style,
42
+ isMobile = false,
43
+ isFirst = false,
44
+ isLast = false,
45
+ onMoveUp,
46
+ onMoveDown,
29
47
  }, ref) => {
48
+ const qtyLabel = labels.quantity ?? 'Qty'
49
+ const capLabel = labels.capacity ?? 'Cap'
50
+ const totalLabel = labels.total ?? 'Total'
30
51
  const classes = [
31
52
  'zone-card__resource',
32
53
  onClick ? 'zone-card__resource--clickable' : '',
54
+ isMobile ? 'zone-card__resource--mobile' : '',
33
55
  className,
34
56
  ].filter(Boolean).join(' ')
35
57
 
36
58
  return (
37
59
  <div ref={ref} className={classes} style={style} onClick={onClick}>
38
- {draggable && (
60
+ {draggable && !isMobile && (
39
61
  <div
40
62
  className="zone-card__drag-handle zone-card__drag-handle--resource"
41
63
  {...dragHandleProps}
42
64
  onClick={(e) => e.stopPropagation()}
43
65
  >
44
- {GripVerticalIcon({ width: 14, height: 14 })}
66
+ {GripVerticalIcon({ width: 16, height: 16 })}
67
+ </div>
68
+ )}
69
+ {draggable && isMobile && (
70
+ <div className="zone-card__reorder-arrows zone-card__reorder-arrows--resource" onClick={(e) => e.stopPropagation()}>
71
+ <button
72
+ className="zone-card__arrow-btn"
73
+ disabled={isFirst}
74
+ onClick={(e) => { e.stopPropagation(); onMoveUp?.() }}
75
+ >
76
+ <ArrowUpIcon />
77
+ </button>
78
+ <button
79
+ className="zone-card__arrow-btn"
80
+ disabled={isLast}
81
+ onClick={(e) => { e.stopPropagation(); onMoveDown?.() }}
82
+ >
83
+ <ArrowDownIcon />
84
+ </button>
45
85
  </div>
46
86
  )}
47
87
  <span className="zone-card__resource-name">{name}</span>
48
- <div className="zone-card__resource-stats">
49
- <span className="zone-card__resource-stat">Qty: {quantity}</span>
50
- <span className="zone-card__resource-stat">Cap: {capacity}</span>
51
- <span className="zone-card__resource-stat zone-card__resource-stat--total">
52
- Total: {quantity * capacity}
88
+ {!isMobile && (
89
+ <div className="zone-card__resource-stats">
90
+ <span className="zone-card__resource-stat">{qtyLabel}: {quantity}</span>
91
+ <span className="zone-card__resource-stat">{capLabel}: {capacity}</span>
92
+ <span className="zone-card__resource-stat zone-card__resource-stat--total">
93
+ {totalLabel}: {quantity * capacity}
94
+ </span>
95
+ </div>
96
+ )}
97
+ {isMobile && (
98
+ <span className="zone-card__resource-stats-mobile">
99
+ {qtyLabel}: {quantity} &middot; {capLabel}: {capacity} &middot; {totalLabel}: {quantity * capacity}
53
100
  </span>
54
- </div>
101
+ )}
55
102
  {menuItems.length > 0 && (
56
103
  <div className="zone-card__resource-actions" onClick={(e) => e.stopPropagation()}>
57
104
  <ActionMenu items={menuItems} />
@@ -7,7 +7,7 @@
7
7
  &__header {
8
8
  display: flex;
9
9
  align-items: center;
10
- gap: 12px;
10
+ gap: 16px;
11
11
  padding: 12px 16px;
12
12
  background: var(--surface-secondary);
13
13
  }
@@ -15,14 +15,15 @@
15
15
  &__drag-handle {
16
16
  display: flex;
17
17
  align-items: center;
18
- padding: 4px;
19
- border-radius: 4px;
18
+ padding: 6px;
19
+ border-radius: 6px;
20
20
  cursor: grab;
21
- color: var(--label-secondary);
21
+ color: var(--label-tertiary, var(--label-secondary));
22
22
  transition: all 0.2s ease;
23
+ flex-shrink: 0;
23
24
 
24
25
  &:hover {
25
- color: var(--label-primary);
26
+ color: var(--label-secondary);
26
27
  background: var(--surface-primary);
27
28
  }
28
29
 
@@ -31,7 +32,44 @@
31
32
  }
32
33
 
33
34
  &--resource {
35
+ color: var(--label-tertiary, var(--label-secondary));
36
+ }
37
+ }
38
+
39
+ // Mobile reorder arrows (replaces drag handles)
40
+ &__reorder-arrows {
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: 2px;
44
+ flex-shrink: 0;
45
+
46
+ &--resource {
47
+ margin-right: 0;
48
+ }
49
+ }
50
+
51
+ &__arrow-btn {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ width: 28px;
56
+ height: 28px;
57
+ border: none;
58
+ border-radius: 4px;
59
+ background: transparent;
60
+ color: var(--label-tertiary, var(--label-secondary));
61
+ cursor: pointer;
62
+ transition: all 0.2s ease;
63
+ padding: 0;
64
+
65
+ &:hover:not(:disabled) {
34
66
  color: var(--label-secondary);
67
+ background: var(--surface-primary);
68
+ }
69
+
70
+ &:disabled {
71
+ opacity: 0.25;
72
+ pointer-events: none;
35
73
  }
36
74
  }
37
75
 
@@ -48,7 +86,7 @@
48
86
  &__header-right {
49
87
  display: flex;
50
88
  align-items: center;
51
- gap: 12px;
89
+ gap: 16px;
52
90
  flex-shrink: 0;
53
91
  }
54
92
 
@@ -59,13 +97,15 @@
59
97
  line-height: 16px;
60
98
  color: var(--label-secondary);
61
99
  white-space: nowrap;
100
+ min-width: 72px;
101
+ text-align: right;
62
102
  }
63
103
 
64
104
  // Resource rows
65
105
  &__resource {
66
106
  display: flex;
67
107
  align-items: center;
68
- gap: 12px;
108
+ gap: 16px;
69
109
  padding: 10px 16px 10px 32px;
70
110
  border-top: 1px solid var(--border-primary);
71
111
  transition: background 0.2s ease;
@@ -77,6 +117,11 @@
77
117
  background: var(--surface-secondary);
78
118
  }
79
119
  }
120
+
121
+ &--mobile {
122
+ flex-wrap: wrap;
123
+ padding-left: 16px;
124
+ }
80
125
  }
81
126
 
82
127
  &__resource-name {
@@ -103,14 +148,24 @@
103
148
  line-height: 16px;
104
149
  color: var(--label-secondary);
105
150
  white-space: nowrap;
106
- min-width: 56px;
151
+ min-width: 72px;
107
152
 
108
153
  &--total {
109
- min-width: 56px;
154
+ min-width: 72px;
110
155
  text-align: right;
111
156
  }
112
157
  }
113
158
 
159
+ // Mobile-only compact stats line
160
+ &__resource-stats-mobile {
161
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
162
+ font-size: 12px;
163
+ font-weight: 400;
164
+ line-height: 16px;
165
+ color: var(--label-secondary);
166
+ white-space: nowrap;
167
+ }
168
+
114
169
  &__resource-actions {
115
170
  flex-shrink: 0;
116
171
  width: 32px;
@@ -127,8 +182,13 @@
127
182
 
128
183
  @media (max-width: 768px) {
129
184
  .zone-card {
185
+ &__header {
186
+ padding: 10px 12px;
187
+ }
188
+
130
189
  &__resource {
131
- padding-left: 16px;
190
+ padding: 10px 12px 10px 12px;
191
+ gap: 12px;
132
192
  }
133
193
 
134
194
  &__resource-stats {
@@ -138,5 +198,9 @@
138
198
  &__resource-stat {
139
199
  min-width: auto;
140
200
  }
201
+
202
+ &__add-resource-wrapper {
203
+ padding: 10px 12px;
204
+ }
141
205
  }
142
206
  }