proje-react-panel 1.6.0 → 1.8.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.
Files changed (104) hide show
  1. package/.cursor/rules.md +11 -1
  2. package/.vscode/settings.json +1 -1
  3. package/README.md +57 -1
  4. package/dist/__tests__/components/form/CustomField.test.d.ts +4 -0
  5. package/dist/api/ApiConfig.d.ts +11 -0
  6. package/dist/api/AuthApi.d.ts +2 -5
  7. package/dist/api/CrudApi.d.ts +11 -12
  8. package/dist/components/DashboardContainer.d.ts +7 -0
  9. package/dist/components/DashboardGrid.d.ts +9 -0
  10. package/dist/components/DashboardItem.d.ts +10 -0
  11. package/dist/components/ThemeSwitcher.d.ts +7 -0
  12. package/dist/components/dashboard/Dashboard.d.ts +7 -0
  13. package/dist/components/dashboard/DashboardGrid.d.ts +7 -0
  14. package/dist/components/dashboard/DashboardItem.d.ts +6 -0
  15. package/dist/components/dashboard/index.d.ts +3 -0
  16. package/dist/components/form/CustomField.d.ts +9 -0
  17. package/dist/decorators/auth/DefaultLoginForm.d.ts +4 -0
  18. package/dist/decorators/form/Input.d.ts +1 -1
  19. package/dist/decorators/form/inputs/CustomInput.d.ts +16 -0
  20. package/dist/index.cjs.js +15 -1
  21. package/dist/index.d.ts +7 -0
  22. package/dist/index.esm.js +15 -1
  23. package/dist/store/themeStore.d.ts +23 -0
  24. package/dist/types/Login.d.ts +8 -0
  25. package/guides/AUTH_LAYOUT_EXAMPLE.md +343 -0
  26. package/guides/AUTH_LAYOUT_GUIDE.md +819 -0
  27. package/guides/COLOR_SYSTEM_GUIDE.md +296 -0
  28. package/guides/DASHBOARD_GUIDE.md +531 -0
  29. package/guides/IMPLEMENTATION_GUIDE.md +899 -0
  30. package/guides/USAGE.md +85 -0
  31. package/how_to.md +184 -0
  32. package/package.json +7 -1
  33. package/src/__tests__/components/form/CustomField.test.tsx +92 -0
  34. package/src/api/ApiConfig.ts +63 -0
  35. package/src/api/AuthApi.ts +8 -0
  36. package/src/api/CrudApi.ts +96 -60
  37. package/src/components/dashboard/Dashboard.tsx +11 -0
  38. package/src/components/dashboard/DashboardGrid.tsx +14 -0
  39. package/src/components/dashboard/DashboardItem.tsx +9 -0
  40. package/src/components/dashboard/index.ts +3 -0
  41. package/src/components/form/CustomField.tsx +34 -0
  42. package/src/components/form/FormField.tsx +5 -1
  43. package/src/components/layout/Layout.tsx +18 -2
  44. package/src/components/list/ListPage.tsx +1 -1
  45. package/src/decorators/auth/DefaultLoginForm.ts +32 -0
  46. package/src/decorators/form/Input.ts +1 -1
  47. package/src/decorators/form/inputs/CustomInput.ts +26 -0
  48. package/src/index.ts +31 -0
  49. package/src/styles/base/_variables.scss +45 -0
  50. package/src/styles/components/button.scss +3 -3
  51. package/src/styles/components/checkbox.scss +6 -6
  52. package/src/styles/components/form-header.scss +21 -19
  53. package/src/styles/components/uploader.scss +15 -37
  54. package/src/styles/counter.scss +25 -33
  55. package/src/styles/dashboard.scss +9 -0
  56. package/src/styles/details.scss +6 -15
  57. package/src/styles/error-boundary.scss +75 -74
  58. package/src/styles/filter-popup.scss +29 -27
  59. package/src/styles/form.scss +16 -15
  60. package/src/styles/index.scss +8 -4
  61. package/src/styles/layout.scss +9 -8
  62. package/src/styles/list.scss +29 -27
  63. package/src/styles/loading-screen.scss +4 -4
  64. package/src/styles/login.scss +3 -3
  65. package/src/styles/pagination.scss +13 -13
  66. package/src/styles/sidebar.scss +24 -22
  67. package/src/styles/utils/scrollbar.scss +4 -3
  68. package/src/types/Login.ts +9 -0
  69. package/src/utils/logout.ts +2 -0
  70. package/dist/components/components/Checkbox.d.ts +0 -7
  71. package/dist/components/components/Counter.d.ts +0 -9
  72. package/dist/components/components/ErrorBoundary.d.ts +0 -16
  73. package/dist/components/components/ErrorComponent.d.ts +0 -4
  74. package/dist/components/components/FormField.d.ts +0 -17
  75. package/dist/components/components/ImageUploader.d.ts +0 -15
  76. package/dist/components/components/InnerForm.d.ts +0 -17
  77. package/dist/components/components/Label.d.ts +0 -9
  78. package/dist/components/components/LoadingScreen.d.ts +0 -2
  79. package/dist/components/components/Uploader.d.ts +0 -8
  80. package/dist/components/components/index.d.ts +0 -8
  81. package/dist/components/components/list/Datagrid.d.ts +0 -9
  82. package/dist/components/components/list/EmptyList.d.ts +0 -2
  83. package/dist/components/components/list/FilterPopup.d.ts +0 -11
  84. package/dist/components/components/list/ListPage.d.ts +0 -20
  85. package/dist/components/components/list/Pagination.d.ts +0 -11
  86. package/dist/components/components/list/index.d.ts +0 -0
  87. package/dist/components/pages/ControllerDetails.d.ts +0 -5
  88. package/dist/components/pages/FormPage.d.ts +0 -18
  89. package/dist/components/pages/ListPage.d.ts +0 -18
  90. package/dist/components/pages/Login.d.ts +0 -13
  91. package/dist/decorators/Crud.d.ts +0 -6
  92. package/dist/decorators/form/FormOptions.d.ts +0 -7
  93. package/dist/decorators/form/getFormFields.d.ts +0 -3
  94. package/dist/decorators/list/GetCellFields.d.ts +0 -2
  95. package/dist/decorators/list/ImageCell.d.ts +0 -6
  96. package/dist/decorators/list/ListData.d.ts +0 -6
  97. package/dist/decorators/list/getListFields.d.ts +0 -2
  98. package/dist/initPanel.d.ts +0 -2
  99. package/dist/types/Screen.d.ts +0 -4
  100. package/dist/types/ScreenCreatorData.d.ts +0 -13
  101. package/dist/types/getDetailsData.d.ts +0 -1
  102. package/dist/types/initPanelOptions.d.ts +0 -2
  103. package/dist/utils/createScreens.d.ts +0 -1
  104. package/dist/utils/getFields.d.ts +0 -3
@@ -0,0 +1,3 @@
1
+ export { Dashboard } from './Dashboard';
2
+ export { DashboardGrid } from './DashboardGrid';
3
+ export { DashboardItem } from './DashboardItem';
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { InputConfiguration } from '../../decorators/form/Input';
3
+ import { useFormContext, Controller } from 'react-hook-form';
4
+ import { CustomInputConfiguration } from '../../decorators/form/inputs/CustomInput';
5
+
6
+ interface CustomFieldProps {
7
+ input: InputConfiguration;
8
+ fieldName: string;
9
+ error?: string;
10
+ }
11
+
12
+ export function CustomField({ input, fieldName, error }: CustomFieldProps) {
13
+ const inputCustom = input as CustomInputConfiguration;
14
+ const { control } = useFormContext();
15
+
16
+ return (
17
+ <Controller
18
+ name={fieldName}
19
+ control={control}
20
+ render={({ field }) => {
21
+ return (
22
+ <>
23
+ {inputCustom.render({
24
+ fieldName,
25
+ value: field.value,
26
+ onChange: field.onChange,
27
+ error,
28
+ })}
29
+ </>
30
+ );
31
+ }}
32
+ />
33
+ );
34
+ }
@@ -5,6 +5,7 @@ import { Uploader } from './Uploader';
5
5
  import { Checkbox } from './Checkbox';
6
6
  import { Label } from './Label';
7
7
  import { Select } from './Select';
8
+ import { CustomField } from './CustomField';
8
9
 
9
10
  interface FormFieldProps {
10
11
  input: InputConfiguration;
@@ -82,6 +83,8 @@ export function FormField({ input, register, error, baseName }: FormFieldProps)
82
83
  return <textarea {...register(fieldName)} placeholder={input.placeholder} />;
83
84
  case 'select':
84
85
  return <Select input={input} fieldName={fieldName} />;
86
+ case 'custom':
87
+ return <CustomField input={input} fieldName={fieldName} error={error?.message} />;
85
88
  case 'input': {
86
89
  return (
87
90
  <input type={input.inputType} {...register(fieldName)} placeholder={input.placeholder} />
@@ -98,7 +101,8 @@ export function FormField({ input, register, error, baseName }: FormFieldProps)
98
101
  default:
99
102
  return null;
100
103
  }
101
- }, [input, register, fieldName]);
104
+ // NOTE: error message is a dependency because 'custom' forwards it into the render prop.
105
+ }, [input, register, fieldName, error?.message]);
102
106
 
103
107
  return (
104
108
  <div className={`form-field ${input.type === 'nested' ? 'nested-form-field' : ''}`}>
@@ -1,5 +1,6 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { SideBar } from './SideBar';
3
+ import { LoadingScreen } from '../LoadingScreen';
3
4
  import { useAppStore } from '../../store/store';
4
5
 
5
6
  export function Layout<IconType>({
@@ -16,8 +17,23 @@ export function Layout<IconType>({
16
17
  const { user } = useAppStore(s => ({
17
18
  user: s.user,
18
19
  }));
19
- if (!user) {
20
+ const redirected = useRef(false);
21
+
22
+ // Yonlendirme render govdesinde degil effect'te yapiliyor: render sirasindaki
23
+ // yan etki React kuralini ihlal ediyor ve StrictMode'da iki kez tetikleniyordu.
24
+ useEffect(() => {
25
+ if (user || redirected.current) {
26
+ return;
27
+ }
28
+ redirected.current = true;
20
29
  logout?.('redirect');
30
+ }, [user, logout]);
31
+
32
+ // Oturum yokken children RENDER EDILMEZ. Eskiden `logout('redirect')` cagrilip
33
+ // yine de tum layout donuluyordu; tarayici korumali ekrani boyayip ancak
34
+ // ondan sonra login'e gidiyordu (panelin bir an gorunup kaybolmasi).
35
+ if (!user) {
36
+ return <LoadingScreen id="layout-auth-redirect" />;
21
37
  }
22
38
 
23
39
  return (
@@ -60,7 +60,7 @@ export function ListPage<T extends AnyClass>({
60
60
  const filtersFromUrl: Record<string, string> = {};
61
61
  searchParams.forEach((value, key) => {
62
62
  filtersFromUrl[key] = value;
63
- });
63
+ });
64
64
  setActiveFilters(filtersFromUrl);
65
65
  }, []);
66
66
 
@@ -0,0 +1,32 @@
1
+ import { MinLength } from 'class-validator';
2
+ import { Form } from '../form/Form';
3
+ import { Input } from '../form/Input';
4
+ import { LoginForm as LoginFormInterface, LoginResponse } from '../../types/Login';
5
+ import { setAuthToken } from '../../api/ApiConfig';
6
+ import { login } from '../../utils/login';
7
+ import { User } from '../../types/User';
8
+ import { authLogin } from '../..';
9
+
10
+ @Form<LoginFormInterface, LoginResponse<User>>({
11
+ onSubmit: authLogin,
12
+ onSubmitSuccess: (data: LoginResponse<User>) => {
13
+ setAuthToken(data.access_token);
14
+ login(data.admin as User, data.access_token, () => {
15
+ window.location.href = '/';
16
+ });
17
+ },
18
+ type: 'formData',
19
+ })
20
+ export class DefaultLoginForm {
21
+ @MinLength(3)
22
+ @Input({
23
+ label: 'Username',
24
+ })
25
+ username: string;
26
+
27
+ @Input({
28
+ label: 'Password',
29
+ inputType: 'password',
30
+ })
31
+ password: string;
32
+ }
@@ -8,7 +8,7 @@ const isFieldSensitive = (fieldName: string): boolean => {
8
8
  };
9
9
 
10
10
  export type InputTypes = 'input' | 'textarea' | 'file-upload' | 'checkbox' | 'hidden' | 'nested';
11
- export type ExtendedInputTypes = InputTypes | 'select';
11
+ export type ExtendedInputTypes = InputTypes | 'select' | 'custom';
12
12
 
13
13
  export interface InputOptions {
14
14
  type?: InputTypes;
@@ -0,0 +1,26 @@
1
+ import type { ReactNode } from 'react';
2
+ import { ExtendedInput, ExtendedInputOptions, InputConfiguration, InputOptions } from '../Input';
3
+
4
+ export interface CustomRenderProps {
5
+ fieldName: string;
6
+ value: unknown;
7
+ onChange: (value: unknown) => void;
8
+ error?: string;
9
+ }
10
+
11
+ export interface CustomInputOptions extends Omit<InputOptions, 'type'> {
12
+ render: (props: CustomRenderProps) => ReactNode;
13
+ }
14
+
15
+ export interface CustomInputConfiguration extends InputConfiguration {
16
+ type: 'custom';
17
+ render: (props: CustomRenderProps) => ReactNode;
18
+ }
19
+
20
+ //NOTE: the render function travels through Reflect metadata like any other option value.
21
+ export function CustomInput(options: CustomInputOptions): PropertyDecorator {
22
+ return ExtendedInput({
23
+ ...options,
24
+ type: 'custom',
25
+ } as ExtendedInputOptions);
26
+ }
package/src/index.ts CHANGED
@@ -21,6 +21,11 @@ export { FormPage } from './components/form/FormPage';
21
21
  export { Form, type OnSubmitFN } from './decorators/form/Form';
22
22
  export { Input } from './decorators/form/Input';
23
23
  export { SelectInput } from './decorators/form/inputs/SelectInput';
24
+ export {
25
+ CustomInput,
26
+ type CustomInputOptions,
27
+ type CustomRenderProps,
28
+ } from './decorators/form/inputs/CustomInput';
24
29
  //for nested form fields
25
30
  export { getInputFields } from './decorators/form/Input';
26
31
 
@@ -29,6 +34,7 @@ export { Panel } from './components/Panel';
29
34
 
30
35
  //DASHBOARD
31
36
  export { Counter } from './components/Counter';
37
+ export { Dashboard, DashboardGrid, DashboardItem } from './components/dashboard';
32
38
 
33
39
  //LAYOUT
34
40
  export { Layout } from './components/layout';
@@ -37,6 +43,31 @@ export { Layout } from './components/layout';
37
43
  export { Login } from './components/Login';
38
44
  export { login } from './utils/login';
39
45
  export { logout } from './utils/logout';
46
+ export { DefaultLoginForm } from './decorators/auth/DefaultLoginForm';
47
+
48
+ //API
49
+ export {
50
+ initApi,
51
+ initAuthToken,
52
+ setAuthToken,
53
+ setAuthLogout,
54
+ getAxiosInstance,
55
+ axiosInstance,
56
+ } from './api/ApiConfig';
57
+ export {
58
+ getAll,
59
+ getOne,
60
+ create,
61
+ createFormData,
62
+ update,
63
+ updateFormData,
64
+ updateSimple,
65
+ remove,
66
+ } from './api/CrudApi';
67
+ export { login as authLogin } from './api/AuthApi';
68
+
69
+ //TYPES
70
+ export type { LoginForm, LoginResponse } from './types/Login';
40
71
 
41
72
  //SERVICES
42
73
  export { updateDetailsData } from './services/DataService';
@@ -0,0 +1,45 @@
1
+ // SCSS Color Variables - Dark Theme
2
+ // ⚠️ IMPORTANT: If you change any variables here, you MUST update COLOR_SYSTEM_GUIDE.md
3
+ $dark-void: #1a1a1a; // Darkest background
4
+ $dark-slate: #2b2b2b; // Dark background
5
+ $dark-mist: #333333; // Medium dark background
6
+ $dark-silver: #444444; // Lighter dark background
7
+
8
+ $dark-pearl: #ffffff; // White
9
+ $dark-ash: #e0e0e0; // Light gray
10
+ $dark-dust: #999999; // Medium gray
11
+
12
+ $dark-ocean: #007bff; // Primary blue
13
+ $dark-sky: #66b2ff; // Light blue (focus)
14
+ $dark-emerald: #4caf50; // Success green
15
+ $dark-ruby: #ff4d4f; // Error red
16
+
17
+ .layout {
18
+ // Backgrounds
19
+ --prp-bg-primary: #{$dark-void};
20
+ --prp-bg-secondary: #{$dark-slate};
21
+ --prp-bg-tertiary: #{$dark-mist};
22
+ --prp-bg-white: #{$dark-pearl};
23
+ --prp-bg-button-primary: #{$dark-ocean};
24
+ --prp-bg-button-success: #{$dark-emerald};
25
+
26
+ // Text
27
+ --prp-text-primary: #{$dark-pearl};
28
+ --prp-text-secondary: #{$dark-ash};
29
+ --prp-text-muted: #{$dark-dust};
30
+
31
+ // Borders
32
+ --prp-border-primary: #{$dark-silver};
33
+ --prp-border-light: #{$dark-ash};
34
+
35
+ // Colors
36
+ --prp-color-focus: #{$dark-sky};
37
+ --prp-color-success: #{$dark-emerald};
38
+ --prp-color-error: #{$dark-ruby};
39
+
40
+ // Shadows
41
+ --prp-shadow-light: rgba(0, 0, 0, 0.05);
42
+ --prp-shadow-medium: rgba(0, 0, 0, 0.2);
43
+ --prp-shadow-dark: rgba(0, 0, 0, 0.3);
44
+ --prp-shadow-focus: rgba(102, 178, 255, 0.2);
45
+ }
@@ -1,9 +1,9 @@
1
1
  .panel-button {
2
2
  padding: 0.5rem 1rem;
3
- border: 1px solid #444444;
3
+ border: 1px solid var(--prp-border-primary);
4
4
  border-radius: 4px;
5
- background-color: cornflowerblue;
6
- color: #ffffff;
5
+ background-color: var(--prp-bg-button-primary);
6
+ color: var(--prp-text-primary);
7
7
  font-size: 0.875rem;
8
8
  font-weight: 500;
9
9
  cursor: pointer;
@@ -13,10 +13,10 @@ input.apple-switch {
13
13
  outline: none;
14
14
  width: 50px;
15
15
  height: 30px;
16
- background-color: #fff;
16
+ background-color: var(--prp-bg-white);
17
17
  border: 1px solid #d9dadc;
18
18
  border-radius: 50px;
19
- box-shadow: inset -20px 0 0 0 #fff;
19
+ box-shadow: inset -20px 0 0 0 var(--prp-bg-white);
20
20
  }
21
21
 
22
22
  input.apple-switch:after {
@@ -28,15 +28,15 @@ input.apple-switch:after {
28
28
  width: 26px;
29
29
  height: 26px;
30
30
  border-radius: 50%;
31
- box-shadow: 2px 4px 6px rgba(0, 0, 0, 0.2);
31
+ box-shadow: 2px 4px 6px var(--prp-shadow-medium);
32
32
  }
33
33
 
34
34
  input.apple-switch:checked {
35
- box-shadow: inset 20px 0 0 0 #4ed164;
36
- border-color: #4ed164;
35
+ box-shadow: inset 20px 0 0 0 var(--prp-color-success);
36
+ border-color: var(--prp-color-success);
37
37
  }
38
38
 
39
39
  input.apple-switch:checked:after {
40
40
  left: 20px;
41
- box-shadow: -2px 4px 3px rgba(0, 0, 0, 0.05);
41
+ box-shadow: -2px 4px 3px var(--prp-shadow-light);
42
42
  }
@@ -4,14 +4,14 @@
4
4
  align-items: center;
5
5
  padding: 1rem;
6
6
  margin-bottom: 1.5rem;
7
- background-color: #333333;
7
+ background-color: var(--prp-bg-tertiary);
8
8
  border-radius: 8px 0 0 8px;
9
9
 
10
10
  .form-title {
11
11
  margin: 0;
12
12
  font-size: 1.5rem;
13
13
  font-weight: 600;
14
- color: #cccccc;
14
+ color: var(--prp-text-secondary);
15
15
  }
16
16
 
17
17
  .form-header-inner {
@@ -23,50 +23,52 @@
23
23
  .export-button,
24
24
  .import-button {
25
25
  padding: 0.5rem 1rem;
26
- border: 1px solid #444444;
26
+ border: 1px solid var(--prp-border-primary);
27
27
  border-radius: 4px;
28
- background-color: #222222;
29
- color: #cccccc;
28
+ background-color: var(--prp-bg-secondary);
29
+ color: var(--prp-text-secondary);
30
30
  font-size: 0.875rem;
31
31
  cursor: pointer;
32
32
  transition: all 0.2s ease;
33
33
 
34
34
  &:hover {
35
- background-color: #444444;
36
- border-color: #555555;
35
+ background-color: var(--prp-bg-tertiary);
36
+ border-color: var(--prp-border-primary);
37
37
  }
38
38
  }
39
39
  }
40
40
 
41
41
  &.dark-theme {
42
- background-color: black;
42
+ background-color: var(--prp-bg-primary);
43
43
  box-shadow: none;
44
44
 
45
45
  .form-title {
46
- color: white;
46
+ color: var(--prp-text-primary);
47
47
  }
48
48
 
49
49
  .form-actions {
50
50
  .export-button {
51
- background-color: black;
52
- border-color: black;
53
- color: white;
51
+ background-color: var(--prp-bg-primary);
52
+ border-color: var(--prp-bg-primary);
53
+ color: var(--prp-text-primary);
54
54
 
55
55
  &:hover {
56
- background-color: black;
57
- border-color: black;
56
+ background-color: var(--prp-bg-primary);
57
+ border-color: var(--prp-bg-primary);
58
+ opacity: 0.9;
58
59
  }
59
60
  }
60
61
 
61
62
  .import-button {
62
63
  .import-label {
63
- background-color: black;
64
- border-color: black;
65
- color: white;
64
+ background-color: var(--prp-bg-primary);
65
+ border-color: var(--prp-bg-primary);
66
+ color: var(--prp-text-primary);
66
67
 
67
68
  &:hover {
68
- background-color: black;
69
- border-color: black;
69
+ background-color: var(--prp-bg-primary);
70
+ border-color: var(--prp-bg-primary);
71
+ opacity: 0.9;
70
72
  }
71
73
  }
72
74
  }
@@ -1,19 +1,20 @@
1
1
  .uploader {
2
2
  &-container {
3
3
  padding: 1.5rem;
4
- border: 2px dashed var(--border-color, #e0e0e0);
4
+ border: 2px dashed var(--prp-border-light);
5
5
  border-radius: 8px;
6
- background-color: var(--bg-color, #fafafa);
6
+ background-color: var(--prp-bg-white);
7
7
  transition: all 0.3s ease;
8
8
 
9
9
  &:hover {
10
- border-color: var(--primary-color, #2196f3);
11
- background-color: var(--bg-hover-color, #f5f5f5);
10
+ border-color: var(--prp-bg-button-primary);
11
+ background-color: var(--prp-bg-tertiary);
12
+ opacity: 0.9;
12
13
  }
13
14
  }
14
15
 
15
16
  &-button {
16
- background-color: var(--primary-color, #2196f3);
17
+ background-color: var(--prp-bg-button-primary);
17
18
  color: var(--button-text-color, white);
18
19
  padding: 0.75rem 1.5rem;
19
20
  border: none;
@@ -23,11 +24,13 @@
23
24
  transition: background-color 0.3s ease;
24
25
 
25
26
  &:hover {
26
- background-color: var(--primary-hover-color, #1976d2);
27
+ background-color: var(--prp-bg-button-primary);
28
+ opacity: 0.9;
27
29
  }
28
30
 
29
31
  &:active {
30
- background-color: var(--primary-active-color, #1565c0);
32
+ background-color: var(--prp-bg-button-primary);
33
+ opacity: 0.8;
31
34
  }
32
35
  }
33
36
 
@@ -38,49 +41,24 @@
38
41
  }
39
42
 
40
43
  &-file {
41
- background-color: var(--file-bg-color, white);
44
+ background-color: var(--prp-bg-secondary);
42
45
  padding: 1rem;
43
46
  border-radius: 6px;
44
- box-shadow: 0 2px 4px var(--shadow-color, rgba(0, 0, 0, 0.05));
47
+ box-shadow: 0 2px 4px var(--prp-shadow-light);
45
48
  display: grid;
46
49
  gap: 0.5rem;
47
50
 
48
51
  p {
49
52
  margin: 0;
50
- color: var(--text-color, #424242);
53
+ color: var(--prp-text-muted);
51
54
  font-size: 0.875rem;
52
55
 
53
56
  &:first-child {
54
- color: var(--primary-color, #1976d2);
57
+ color: var(--prp-bg-button-primary);
55
58
  font-weight: 500;
56
59
  }
57
60
  }
58
61
  }
59
62
  }
60
63
 
61
- :root {
62
- --border-color: #424242;
63
- --bg-color: #1e1e1e;
64
- --bg-hover-color: #2d2d2d;
65
- --primary-color: #64b5f6;
66
- --primary-hover-color: #42a5f5;
67
- --primary-active-color: #2196f3;
68
- --button-text-color: #ffffff;
69
- --file-bg-color: #2d2d2d;
70
- --shadow-color: rgba(0, 0, 0, 0.2);
71
- --text-color: #e0e0e0;
72
- }
73
-
74
- // Dark theme
75
- [data-theme='dark'] {
76
- --border-color: #424242;
77
- --bg-color: #1e1e1e;
78
- --bg-hover-color: #2d2d2d;
79
- --primary-color: #64b5f6;
80
- --primary-hover-color: #42a5f5;
81
- --primary-active-color: #2196f3;
82
- --button-text-color: #ffffff;
83
- --file-bg-color: #2d2d2d;
84
- --shadow-color: rgba(0, 0, 0, 0.2);
85
- --text-color: #e0e0e0;
86
- }
64
+ // Note: Background colors are now managed in base/_variables.scss
@@ -1,42 +1,34 @@
1
- // Variables
2
- $primary-color: #007bff;
3
- $text-color: #ffffff;
4
- $bg-color: #1a1a1a;
5
- $shadow-color: rgba(0, 0, 0, 0.3);
6
-
7
1
  // Mixins
8
2
  @mixin flex-center {
9
- display: flex;
10
- align-items: center;
3
+ display: flex;
4
+ align-items: center;
11
5
  }
12
6
 
13
7
  .counter {
14
- &-container {
15
- @include flex-center;
16
- flex-direction: column;
17
- padding: 20px;
18
- border-radius: 8px;
19
- box-shadow: 0 2px 4px $shadow-color;
20
- background-color: $bg-color;
21
- max-width: 300px;
22
- margin: 20px auto;
23
- }
8
+ &-container {
9
+ @include flex-center;
10
+ flex-direction: column;
11
+ padding: 20px;
12
+ border-radius: 8px;
13
+ max-width: 300px;
14
+ margin: 20px auto;
15
+ }
24
16
 
25
- &-image {
26
- margin-bottom: 15px;
27
- }
17
+ &-image {
18
+ margin-bottom: 15px;
19
+ }
28
20
 
29
- &-text {
30
- font-size: 18px;
31
- margin-bottom: 15px;
32
- color: $text-color;
33
- }
21
+ &-text {
22
+ font-size: 18px;
23
+ margin-bottom: 15px;
24
+ color: var(--prp-text-primary);
25
+ }
34
26
 
35
- &-value {
36
- font-size: 24px;
37
- font-weight: bold;
38
- min-width: 40px;
39
- text-align: center;
40
- color: $text-color;
41
- }
27
+ &-value {
28
+ font-size: 24px;
29
+ font-weight: bold;
30
+ min-width: 40px;
31
+ text-align: center;
32
+ color: var(--prp-text-primary);
33
+ }
42
34
  }
@@ -0,0 +1,9 @@
1
+ .dashboard-grid,
2
+ .dashboard {
3
+ display: grid;
4
+ gap: 1rem;
5
+ }
6
+
7
+ .dashboard-item {
8
+ width: 100%;
9
+ }
@@ -1,12 +1,3 @@
1
- :root {
2
- --background-color: #1a1a1a;
3
- --text-color: #e0e0e0;
4
- --label-color: #a0a0a0;
5
- --empty-value-color: #666;
6
- --error-color: #ff6b6b;
7
- --shadow-color: rgba(0, 0, 0, 0.3);
8
- }
9
-
10
1
  .details-page {
11
2
  padding: 2rem;
12
3
  max-width: 1200px;
@@ -17,11 +8,11 @@
17
8
  }
18
9
 
19
10
  .details-item {
20
- background: var(--background-color);
11
+ background: var(--prp-bg-primary);
21
12
  border-radius: 8px;
22
13
  padding: 1.5rem;
23
14
  margin-bottom: 1rem;
24
- box-shadow: 0 2px 4px var(--shadow-color);
15
+ box-shadow: 0 2px 4px var(--prp-shadow-dark);
25
16
  transition: transform 0.2s ease;
26
17
 
27
18
  &:hover {
@@ -30,7 +21,7 @@
30
21
 
31
22
  .item-label {
32
23
  font-size: 0.875rem;
33
- color: var(--label-color);
24
+ color: var(--prp-text-secondary);
34
25
  text-transform: uppercase;
35
26
  letter-spacing: 0.5px;
36
27
  margin-bottom: 0.5rem;
@@ -38,14 +29,14 @@
38
29
 
39
30
  .item-value {
40
31
  font-size: 1rem;
41
- color: var(--text-color);
32
+ color: var(--prp-text-muted);
42
33
  line-height: 1.5;
43
34
  word-break: break-word;
44
35
 
45
36
  &:empty {
46
37
  &::after {
47
38
  content: '—';
48
- color: var(--empty-value-color);
39
+ color: var(--prp-text-muted);
49
40
  }
50
41
  }
51
42
  }
@@ -62,5 +53,5 @@
62
53
  .error-container {
63
54
  padding: 2rem;
64
55
  text-align: center;
65
- color: var(--error-color);
56
+ color: var(--prp-color-error);
66
57
  }