proje-react-panel 1.0.17 → 1.1.1
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.
- package/dist/components/Counter.d.ts +9 -0
- package/dist/components/DetailsPage.d.ts +7 -0
- package/dist/components/ErrorBoundary.d.ts +16 -0
- package/dist/components/ErrorComponent.d.ts +4 -0
- package/dist/components/LoadingScreen.d.ts +2 -0
- package/dist/components/Login.d.ts +13 -0
- package/dist/components/Panel.d.ts +1 -3
- package/dist/components/components/Checkbox.d.ts +3 -2
- package/dist/components/components/FormField.d.ts +5 -1
- package/dist/components/components/InnerForm.d.ts +8 -3
- package/dist/components/components/Label.d.ts +3 -2
- package/dist/components/components/Uploader.d.ts +8 -0
- package/dist/components/components/index.d.ts +1 -1
- package/dist/components/components/list/ListPage.d.ts +1 -1
- package/dist/components/form/Checkbox.d.ts +7 -0
- package/dist/components/form/FormField.d.ts +17 -0
- package/dist/components/form/FormPage.d.ts +6 -0
- package/dist/components/form/InnerForm.d.ts +10 -0
- package/dist/components/form/Label.d.ts +9 -0
- package/dist/components/form/Select.d.ts +8 -0
- package/dist/components/form/SelectStyles.d.ts +7 -0
- package/dist/components/form/Uploader.d.ts +8 -0
- package/dist/components/layout/Layout.d.ts +3 -4
- package/dist/components/layout/SideBar.d.ts +2 -3
- package/dist/components/list/CellField.d.ts +9 -0
- package/dist/components/list/Datagrid.d.ts +6 -8
- package/dist/components/list/FilterPopup.d.ts +7 -5
- package/dist/components/list/ListHeader.d.ts +11 -0
- package/dist/components/list/ListPage.d.ts +6 -0
- package/dist/components/pages/FormPage.d.ts +8 -2
- package/dist/decorators/details/Details.d.ts +11 -0
- package/dist/decorators/details/DetailsItem.d.ts +11 -0
- package/dist/decorators/details/getDetailsPageMeta.d.ts +8 -0
- package/dist/decorators/form/Form.d.ts +16 -5
- package/dist/decorators/form/Input.d.ts +14 -9
- package/dist/decorators/form/getFormPageMeta.d.ts +10 -0
- package/dist/decorators/form/inputs/SelectInput.d.ts +23 -0
- package/dist/decorators/list/Cell.d.ts +13 -1
- package/dist/decorators/list/List.d.ts +18 -1
- package/dist/decorators/list/cells/ImageCell.d.ts +9 -0
- package/dist/decorators/list/getListPageMeta.d.ts +8 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +13 -17
- package/dist/index.esm.js +1 -1
- package/dist/initPanel.d.ts +1 -1
- package/dist/store/store.d.ts +0 -3
- package/dist/types/AnyClass.d.ts +2 -1
- package/dist/types/getDetailsData.d.ts +1 -0
- package/dist/types/initPanelOptions.d.ts +0 -1
- package/package.json +1 -1
- package/src/assets/icons/svg/check.svg +4 -0
- package/src/assets/icons/svg/cross.svg +4 -0
- package/src/components/DetailsPage.tsx +55 -0
- package/src/components/{components/ErrorComponent.tsx → ErrorComponent.tsx} +1 -1
- package/src/components/{pages/Login.tsx → Login.tsx} +2 -2
- package/src/components/Panel.tsx +4 -5
- package/src/components/form/Checkbox.tsx +21 -0
- package/src/components/{components → form}/FormField.tsx +22 -30
- package/src/components/form/FormPage.tsx +32 -0
- package/src/components/form/InnerForm.tsx +84 -0
- package/src/components/form/Label.tsx +21 -0
- package/src/components/form/Select.tsx +51 -0
- package/src/components/form/SelectStyles.ts +73 -0
- package/src/components/form/Uploader.tsx +66 -0
- package/src/components/layout/Layout.tsx +29 -32
- package/src/components/layout/SideBar.tsx +4 -13
- package/src/components/list/CellField.tsx +63 -0
- package/src/components/list/Datagrid.tsx +106 -0
- package/src/components/{components/list → list}/FilterPopup.tsx +13 -9
- package/src/components/list/ListHeader.tsx +47 -0
- package/src/components/{components/list → list}/ListPage.tsx +20 -82
- package/src/decorators/details/Details.ts +31 -0
- package/src/decorators/details/DetailsItem.ts +40 -0
- package/src/decorators/details/getDetailsPageMeta.ts +15 -0
- package/src/decorators/form/Form.ts +38 -12
- package/src/decorators/form/Input.ts +31 -9
- package/src/decorators/form/getFormPageMeta.ts +21 -0
- package/src/decorators/form/inputs/SelectInput.ts +19 -0
- package/src/decorators/list/Cell.ts +41 -1
- package/src/decorators/list/List.ts +30 -6
- package/src/decorators/list/cells/ImageCell.ts +17 -0
- package/src/decorators/list/getListPageMeta.ts +16 -0
- package/src/index.ts +33 -24
- package/src/initPanel.ts +1 -4
- package/src/store/store.ts +0 -5
- package/src/styles/components/checkbox.scss +42 -0
- package/src/styles/components/uploader.scss +86 -0
- package/src/styles/details.scss +62 -0
- package/src/styles/form.scss +9 -11
- package/src/styles/index.scss +26 -12
- package/src/styles/list.scss +3 -1
- package/src/types/AnyClass.ts +2 -1
- package/src/types/initPanelOptions.ts +1 -3
- package/src/components/components/Checkbox.tsx +0 -9
- package/src/components/components/ImageUploader.tsx +0 -301
- package/src/components/components/InnerForm.tsx +0 -74
- package/src/components/components/Label.tsx +0 -15
- package/src/components/components/index.ts +0 -8
- package/src/components/components/list/Datagrid.tsx +0 -127
- package/src/components/pages/ControllerDetails.tsx +0 -37
- package/src/components/pages/FormPage.tsx +0 -34
- package/src/decorators/Crud.ts +0 -20
- package/src/decorators/form/FormOptions.ts +0 -8
- package/src/decorators/form/getFormFields.ts +0 -13
- package/src/decorators/list/GetCellFields.ts +0 -13
- package/src/decorators/list/ImageCell.ts +0 -13
- package/src/decorators/list/ListData.ts +0 -7
- package/src/decorators/list/getListFields.ts +0 -10
- package/src/styles/image-uploader.scss +0 -94
- package/src/types/Screen.ts +0 -4
- package/src/types/ScreenCreatorData.ts +0 -14
- package/src/utils/createScreens.ts +0 -5
- package/src/utils/getFields.ts +0 -22
- /package/src/components/{components/Counter.tsx → Counter.tsx} +0 -0
- /package/src/components/{components/ErrorBoundary.tsx → ErrorBoundary.tsx} +0 -0
- /package/src/components/{components/LoadingScreen.tsx → LoadingScreen.tsx} +0 -0
- /package/src/components/{components/list → list}/EmptyList.tsx +0 -0
- /package/src/components/{components/list → list}/Pagination.tsx +0 -0
- /package/src/components/{components/list → list}/index.ts +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
import 'reflect-metadata';
|
2
|
+
import { AnyClass } from '../../types/AnyClass';
|
2
3
|
|
3
4
|
export const CELL_KEY = Symbol('cell');
|
4
5
|
|
@@ -11,15 +12,39 @@ export interface StaticSelectFilter extends Filter {
|
|
11
12
|
options: { value: string; label: string }[];
|
12
13
|
}
|
13
14
|
|
15
|
+
export type CellTypes = 'string' | 'date' | 'number' | 'boolean' | 'uuid';
|
16
|
+
export type ExtendedCellTypes = CellTypes | 'image';
|
17
|
+
|
14
18
|
export interface CellOptions {
|
15
19
|
name?: string;
|
16
20
|
title?: string;
|
17
|
-
type?:
|
21
|
+
type?: CellTypes;
|
18
22
|
placeHolder?: string;
|
19
23
|
filter?: Filter | StaticSelectFilter;
|
20
24
|
}
|
25
|
+
export interface ExtendedCellOptions extends Omit<CellOptions, 'type'> {
|
26
|
+
type?: ExtendedCellTypes;
|
27
|
+
}
|
28
|
+
|
29
|
+
export interface CellConfiguration extends Omit<CellOptions, 'type'> {
|
30
|
+
name: string;
|
31
|
+
type: ExtendedCellTypes;
|
32
|
+
}
|
21
33
|
|
22
34
|
export function Cell(options?: CellOptions): PropertyDecorator {
|
35
|
+
//TODO: reduce all similar code
|
36
|
+
return (target, propertyKey) => {
|
37
|
+
const existingCells: string[] = Reflect.getMetadata(CELL_KEY, target) || [];
|
38
|
+
Reflect.defineMetadata(CELL_KEY, [...existingCells, propertyKey.toString()], target);
|
39
|
+
|
40
|
+
if (options) {
|
41
|
+
const keyString = `${CELL_KEY.toString()}:${propertyKey.toString()}:options`;
|
42
|
+
Reflect.defineMetadata(keyString, options, target);
|
43
|
+
}
|
44
|
+
};
|
45
|
+
}
|
46
|
+
|
47
|
+
export function ExtendedCell(options?: ExtendedCellOptions): PropertyDecorator {
|
23
48
|
return (target, propertyKey) => {
|
24
49
|
const existingCells: string[] = Reflect.getMetadata(CELL_KEY, target) || [];
|
25
50
|
Reflect.defineMetadata(CELL_KEY, [...existingCells, propertyKey.toString()], target);
|
@@ -30,3 +55,18 @@ export function Cell(options?: CellOptions): PropertyDecorator {
|
|
30
55
|
}
|
31
56
|
};
|
32
57
|
}
|
58
|
+
|
59
|
+
export function getCellFields<T extends AnyClass>(entityClass: T): CellConfiguration[] {
|
60
|
+
const prototype = (entityClass as any).prototype;
|
61
|
+
const inputFields: string[] = Reflect.getMetadata(CELL_KEY, prototype) || [];
|
62
|
+
|
63
|
+
return inputFields.map(field => {
|
64
|
+
const fields: CellOptions =
|
65
|
+
Reflect.getMetadata(`${CELL_KEY.toString()}:${field}:options`, prototype) || {};
|
66
|
+
return {
|
67
|
+
...fields,
|
68
|
+
name: fields.name || field,
|
69
|
+
type: fields.type as ExtendedCellTypes,
|
70
|
+
};
|
71
|
+
});
|
72
|
+
}
|
@@ -1,6 +1,22 @@
|
|
1
1
|
import 'reflect-metadata';
|
2
|
+
import { AnyClass } from '../../types/AnyClass';
|
2
3
|
|
3
|
-
const
|
4
|
+
const LIST_METADATA_KEY = 'ListMetaData';
|
5
|
+
|
6
|
+
export interface GetDataParams {
|
7
|
+
page?: number;
|
8
|
+
limit?: number;
|
9
|
+
filters?: Record<string, any>;
|
10
|
+
}
|
11
|
+
|
12
|
+
export interface PaginatedResponse<T> {
|
13
|
+
data: T[];
|
14
|
+
total: number;
|
15
|
+
page: number;
|
16
|
+
limit: number;
|
17
|
+
}
|
18
|
+
|
19
|
+
export type GetDataForList<T> = (params: GetDataParams) => Promise<PaginatedResponse<T>>;
|
4
20
|
|
5
21
|
export interface ListHeaderOptions {
|
6
22
|
title?: string;
|
@@ -10,23 +26,31 @@ export interface ListHeaderOptions {
|
|
10
26
|
export interface ListCellOptions<T> {
|
11
27
|
details?: { path: string; label: string };
|
12
28
|
edit?: { path: string; label: string };
|
13
|
-
delete?: { label: string };
|
29
|
+
delete?: { label: string; onRemoveItem?: (item: T) => Promise<void> };
|
14
30
|
}
|
15
31
|
|
16
32
|
export interface ListOptions<T> {
|
33
|
+
getData: GetDataForList<T>;
|
17
34
|
headers?: ListHeaderOptions;
|
18
35
|
cells?: ((item: T) => ListCellOptions<T>) | ListCellOptions<T>;
|
19
36
|
}
|
20
37
|
|
38
|
+
export interface ListConfiguration<T> extends ListOptions<T> {}
|
39
|
+
|
21
40
|
export function List<T>(options?: ListOptions<T> | ((item: T) => ListOptions<T>)): ClassDecorator {
|
22
41
|
return (target: Function) => {
|
23
42
|
if (options) {
|
24
|
-
Reflect.defineMetadata(
|
43
|
+
Reflect.defineMetadata(LIST_METADATA_KEY, options, target);
|
25
44
|
}
|
26
45
|
};
|
27
46
|
}
|
28
47
|
|
29
|
-
export function
|
30
|
-
|
31
|
-
|
48
|
+
export function getListConfiguration<T extends AnyClass>(entityClass: T): ListConfiguration<T> {
|
49
|
+
const listConfiguration = Reflect.getMetadata(LIST_METADATA_KEY, entityClass);
|
50
|
+
if (!listConfiguration) {
|
51
|
+
throw new Error('List decerator should be used on class');
|
52
|
+
}
|
53
|
+
return {
|
54
|
+
...listConfiguration,
|
55
|
+
};
|
32
56
|
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import 'reflect-metadata';
|
2
|
+
import { Cell, CellConfiguration, CellOptions, ExtendedCell } from '../Cell';
|
3
|
+
|
4
|
+
export interface ImageCellOptions extends CellOptions {
|
5
|
+
baseUrl: string;
|
6
|
+
}
|
7
|
+
|
8
|
+
export interface ImageCellConfiguration extends CellConfiguration {
|
9
|
+
type: 'image';
|
10
|
+
}
|
11
|
+
|
12
|
+
export function ImageCell(options?: ImageCellOptions): PropertyDecorator {
|
13
|
+
return ExtendedCell({
|
14
|
+
...options,
|
15
|
+
type: 'image',
|
16
|
+
});
|
17
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { AnyClass } from '../../types/AnyClass';
|
2
|
+
import { getDetailsItemFields } from '../details/DetailsItem';
|
3
|
+
import { CellConfiguration, getCellFields } from './Cell';
|
4
|
+
import { getListConfiguration, ListConfiguration } from './List';
|
5
|
+
|
6
|
+
export interface ListPageMeta<T extends AnyClass> {
|
7
|
+
class: ListConfiguration<T>;
|
8
|
+
cells: CellConfiguration[];
|
9
|
+
}
|
10
|
+
|
11
|
+
export function getListPageMeta<T extends AnyClass>(entityClass: T): ListPageMeta<T> {
|
12
|
+
return {
|
13
|
+
class: getListConfiguration(entityClass),
|
14
|
+
cells: getCellFields<T>(entityClass),
|
15
|
+
};
|
16
|
+
}
|
package/src/index.ts
CHANGED
@@ -1,28 +1,37 @@
|
|
1
|
-
|
2
|
-
export
|
3
|
-
export type
|
4
|
-
export
|
5
|
-
export type { AnyClass } from './types/AnyClass';
|
6
|
-
export type {
|
7
|
-
GetDataForList,
|
8
|
-
PaginatedResponse,
|
9
|
-
GetDataParams,
|
10
|
-
} from './components/components/list/ListPage';
|
1
|
+
//DETAILS
|
2
|
+
export { DetailsPage } from './components/DetailsPage';
|
3
|
+
export { Details, type GetDetailsDataFN } from './decorators/details/Details';
|
4
|
+
export { DetailsItem } from './decorators/details/DetailsItem';
|
11
5
|
|
12
|
-
|
13
|
-
export {
|
14
|
-
export
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
export { List } from './decorators/list/List';
|
22
|
-
export { ImageCell } from './decorators/list/ImageCell';
|
23
|
-
export { Crud } from './decorators/Crud';
|
6
|
+
//LIST
|
7
|
+
export { ListPage } from './components/list/ListPage';
|
8
|
+
export {
|
9
|
+
List,
|
10
|
+
type GetDataForList,
|
11
|
+
type PaginatedResponse,
|
12
|
+
type GetDataParams,
|
13
|
+
} from './decorators/list/List';
|
14
|
+
export { ImageCell } from './decorators/list/cells/ImageCell';
|
24
15
|
export { Cell } from './decorators/list/Cell';
|
16
|
+
|
17
|
+
//FORM
|
18
|
+
export { FormPage } from './components/form/FormPage';
|
19
|
+
export { Form, type OnSubmitFN } from './decorators/form/Form';
|
25
20
|
export { Input } from './decorators/form/Input';
|
26
|
-
|
27
|
-
|
21
|
+
export { SelectInput } from './decorators/form/inputs/SelectInput';
|
22
|
+
//for nested form fields
|
28
23
|
export { getInputFields } from './decorators/form/Input';
|
24
|
+
|
25
|
+
//PANEL
|
26
|
+
export { Panel } from './components/Panel';
|
27
|
+
|
28
|
+
//DASHBOARD
|
29
|
+
export { Counter } from './components/Counter';
|
30
|
+
|
31
|
+
//LAYOUT
|
32
|
+
export { Layout } from './components/layout';
|
33
|
+
|
34
|
+
//AUTH
|
35
|
+
export { Login } from './components/Login';
|
36
|
+
|
37
|
+
//UTILS
|
package/src/initPanel.ts
CHANGED
@@ -1,6 +1,3 @@
|
|
1
1
|
import { InitPanelOptions } from './types/initPanelOptions';
|
2
|
-
import { useAppStore } from './store/store';
|
3
2
|
|
4
|
-
export function initPanel({
|
5
|
-
useAppStore.setState({ screenPaths });
|
6
|
-
}
|
3
|
+
export function initPanel({}: InitPanelOptions) {}
|
package/src/store/store.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import { createJSONStorage, persist } from 'zustand/middleware';
|
2
2
|
import { createWithEqualityFn } from 'zustand/traditional';
|
3
3
|
import { shallow } from 'zustand/vanilla/shallow';
|
4
|
-
import { ScreenCreatorData } from '../types/ScreenCreatorData';
|
5
4
|
|
6
5
|
interface User {
|
7
6
|
username: string;
|
@@ -9,16 +8,12 @@ interface User {
|
|
9
8
|
|
10
9
|
interface AppState {
|
11
10
|
user: User | null;
|
12
|
-
screens: Record<string, ScreenCreatorData> | null;
|
13
|
-
screenPaths: Record<string, string>;
|
14
11
|
}
|
15
12
|
|
16
13
|
export const useAppStore = createWithEqualityFn<AppState>()(
|
17
14
|
persist(
|
18
15
|
_ => ({
|
19
|
-
screens: null,
|
20
16
|
user: null,
|
21
|
-
screenPaths: {},
|
22
17
|
}),
|
23
18
|
{
|
24
19
|
name: 'app-store-1',
|
@@ -0,0 +1,42 @@
|
|
1
|
+
.checkbox-label {
|
2
|
+
display: flex;
|
3
|
+
align-items: center;
|
4
|
+
gap: 10px;
|
5
|
+
* {
|
6
|
+
cursor: pointer;
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
input.apple-switch {
|
11
|
+
position: relative;
|
12
|
+
-webkit-appearance: none;
|
13
|
+
outline: none;
|
14
|
+
width: 50px;
|
15
|
+
height: 30px;
|
16
|
+
background-color: #fff;
|
17
|
+
border: 1px solid #d9dadc;
|
18
|
+
border-radius: 50px;
|
19
|
+
box-shadow: inset -20px 0 0 0 #fff;
|
20
|
+
}
|
21
|
+
|
22
|
+
input.apple-switch:after {
|
23
|
+
content: '';
|
24
|
+
position: absolute;
|
25
|
+
top: 1px;
|
26
|
+
left: 1px;
|
27
|
+
background: transparent;
|
28
|
+
width: 26px;
|
29
|
+
height: 26px;
|
30
|
+
border-radius: 50%;
|
31
|
+
box-shadow: 2px 4px 6px rgba(0, 0, 0, 0.2);
|
32
|
+
}
|
33
|
+
|
34
|
+
input.apple-switch:checked {
|
35
|
+
box-shadow: inset 20px 0 0 0 #4ed164;
|
36
|
+
border-color: #4ed164;
|
37
|
+
}
|
38
|
+
|
39
|
+
input.apple-switch:checked:after {
|
40
|
+
left: 20px;
|
41
|
+
box-shadow: -2px 4px 3px rgba(0, 0, 0, 0.05);
|
42
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
.uploader {
|
2
|
+
&-container {
|
3
|
+
padding: 1.5rem;
|
4
|
+
border: 2px dashed var(--border-color, #e0e0e0);
|
5
|
+
border-radius: 8px;
|
6
|
+
background-color: var(--bg-color, #fafafa);
|
7
|
+
transition: all 0.3s ease;
|
8
|
+
|
9
|
+
&:hover {
|
10
|
+
border-color: var(--primary-color, #2196f3);
|
11
|
+
background-color: var(--bg-hover-color, #f5f5f5);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
&-button {
|
16
|
+
background-color: var(--primary-color, #2196f3);
|
17
|
+
color: var(--button-text-color, white);
|
18
|
+
padding: 0.75rem 1.5rem;
|
19
|
+
border: none;
|
20
|
+
border-radius: 4px;
|
21
|
+
font-weight: 500;
|
22
|
+
cursor: pointer;
|
23
|
+
transition: background-color 0.3s ease;
|
24
|
+
|
25
|
+
&:hover {
|
26
|
+
background-color: var(--primary-hover-color, #1976d2);
|
27
|
+
}
|
28
|
+
|
29
|
+
&:active {
|
30
|
+
background-color: var(--primary-active-color, #1565c0);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
&-files {
|
35
|
+
margin-top: 1.5rem;
|
36
|
+
display: grid;
|
37
|
+
gap: 1rem;
|
38
|
+
}
|
39
|
+
|
40
|
+
&-file {
|
41
|
+
background-color: var(--file-bg-color, white);
|
42
|
+
padding: 1rem;
|
43
|
+
border-radius: 6px;
|
44
|
+
box-shadow: 0 2px 4px var(--shadow-color, rgba(0, 0, 0, 0.05));
|
45
|
+
display: grid;
|
46
|
+
gap: 0.5rem;
|
47
|
+
|
48
|
+
p {
|
49
|
+
margin: 0;
|
50
|
+
color: var(--text-color, #424242);
|
51
|
+
font-size: 0.875rem;
|
52
|
+
|
53
|
+
&:first-child {
|
54
|
+
color: var(--primary-color, #1976d2);
|
55
|
+
font-weight: 500;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
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
|
+
}
|
@@ -0,0 +1,62 @@
|
|
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
|
+
.details-page {
|
11
|
+
padding: 2rem;
|
12
|
+
max-width: 1200px;
|
13
|
+
margin: 0 auto;
|
14
|
+
|
15
|
+
.details-item {
|
16
|
+
background: var(--background-color);
|
17
|
+
border-radius: 8px;
|
18
|
+
padding: 1.5rem;
|
19
|
+
margin-bottom: 1rem;
|
20
|
+
box-shadow: 0 2px 4px var(--shadow-color);
|
21
|
+
transition: transform 0.2s ease;
|
22
|
+
|
23
|
+
&:hover {
|
24
|
+
transform: translateY(-2px);
|
25
|
+
}
|
26
|
+
|
27
|
+
.item-label {
|
28
|
+
font-size: 0.875rem;
|
29
|
+
color: var(--label-color);
|
30
|
+
text-transform: uppercase;
|
31
|
+
letter-spacing: 0.5px;
|
32
|
+
margin-bottom: 0.5rem;
|
33
|
+
}
|
34
|
+
|
35
|
+
.item-value {
|
36
|
+
font-size: 1rem;
|
37
|
+
color: var(--text-color);
|
38
|
+
line-height: 1.5;
|
39
|
+
word-break: break-word;
|
40
|
+
|
41
|
+
&:empty {
|
42
|
+
&::after {
|
43
|
+
content: '—';
|
44
|
+
color: var(--empty-value-color);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
.loading-container {
|
52
|
+
display: flex;
|
53
|
+
justify-content: center;
|
54
|
+
align-items: center;
|
55
|
+
min-height: 400px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.error-container {
|
59
|
+
padding: 2rem;
|
60
|
+
text-align: center;
|
61
|
+
color: var(--error-color);
|
62
|
+
}
|
package/src/styles/form.scss
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
.form-wrapper {
|
2
|
-
max-width: 400px;
|
3
2
|
padding: 20px;
|
4
|
-
border-radius: 10px;
|
5
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
6
3
|
background-color: #1a1a1a;
|
7
4
|
color: #f2f2f2;
|
5
|
+
width: 100%;
|
8
6
|
|
9
7
|
form {
|
10
8
|
display: flex;
|
@@ -14,13 +12,6 @@
|
|
14
12
|
.form-field {
|
15
13
|
margin-bottom: 16px;
|
16
14
|
|
17
|
-
label {
|
18
|
-
font-weight: bold;
|
19
|
-
margin-bottom: 6px;
|
20
|
-
display: block;
|
21
|
-
color: #f2f2f2;
|
22
|
-
}
|
23
|
-
|
24
15
|
input[type='text'],
|
25
16
|
input[type='password'],
|
26
17
|
input[type='email'],
|
@@ -59,7 +50,7 @@
|
|
59
50
|
|
60
51
|
select {
|
61
52
|
appearance: none;
|
62
|
-
background-image: url(
|
53
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23FFFFFF%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
|
63
54
|
background-repeat: no-repeat;
|
64
55
|
background-position: right 0.7rem top 50%;
|
65
56
|
background-size: 0.65rem auto;
|
@@ -88,3 +79,10 @@
|
|
88
79
|
}
|
89
80
|
}
|
90
81
|
}
|
82
|
+
|
83
|
+
.label {
|
84
|
+
font-weight: bold;
|
85
|
+
margin-bottom: 6px;
|
86
|
+
display: block;
|
87
|
+
color: #f2f2f2;
|
88
|
+
}
|
package/src/styles/index.scss
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
@
|
2
|
-
|
3
|
-
@
|
4
|
-
@
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
1
|
+
@import './layout';
|
2
|
+
@import './sidebar';
|
3
|
+
@import './form';
|
4
|
+
@import './list';
|
5
|
+
@import './login';
|
6
|
+
@import './error-boundary';
|
7
|
+
@import './counter';
|
8
|
+
@import './loading-screen';
|
9
|
+
@import './pagination';
|
10
|
+
@import './filter-popup';
|
11
|
+
@import './components/uploader.scss';
|
12
|
+
@import './components/checkbox';
|
13
|
+
@import './details';
|
13
14
|
|
15
|
+
//TODO: import deprecated
|
14
16
|
.layout {
|
15
17
|
display: flex;
|
16
18
|
max-height: 100vh;
|
@@ -39,4 +41,16 @@
|
|
39
41
|
height: 14px;
|
40
42
|
stroke: currentColor;
|
41
43
|
fill: currentColor;
|
44
|
+
&.icon-true {
|
45
|
+
width: 20px;
|
46
|
+
height: 20px;
|
47
|
+
stroke: #4caf50;
|
48
|
+
fill: none;
|
49
|
+
}
|
50
|
+
&.icon-false {
|
51
|
+
width: 20px;
|
52
|
+
height: 20px;
|
53
|
+
stroke: #ff0000;
|
54
|
+
fill: none;
|
55
|
+
}
|
42
56
|
}
|
package/src/styles/list.scss
CHANGED
package/src/types/AnyClass.ts
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
export type AnyClass =
|
1
|
+
export type AnyClass = Record<string, any>;
|
2
|
+
export type AnyClassConstructor<T extends AnyClass> = new (...args: any[]) => T;
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
|
3
|
-
interface CheckboxProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
4
|
-
id: string;
|
5
|
-
}
|
6
|
-
|
7
|
-
export function Checkbox({ id, ...props }: CheckboxProps) {
|
8
|
-
return <input type="checkbox" id={id} className="checkbox" {...props} />;
|
9
|
-
}
|