othr
This commit is contained in:
		@@ -12,6 +12,8 @@ export type { AuthLoginResponse } from './models/AuthLoginResponse';
 | 
			
		||||
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
 | 
			
		||||
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
 | 
			
		||||
export type { DealCreateRequest } from './models/DealCreateRequest';
 | 
			
		||||
export type { DealCreateResponse } from './models/DealCreateResponse';
 | 
			
		||||
export type { DealQuickCreateRequest } from './models/DealQuickCreateRequest';
 | 
			
		||||
export type { HTTPValidationError } from './models/HTTPValidationError';
 | 
			
		||||
export type { ValidationError } from './models/ValidationError';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@
 | 
			
		||||
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
 | 
			
		||||
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
 | 
			
		||||
import type { DealCreateRequest } from '../models/DealCreateRequest';
 | 
			
		||||
import type { DealCreateResponse } from '../models/DealCreateResponse';
 | 
			
		||||
import type { DealQuickCreateRequest } from '../models/DealQuickCreateRequest';
 | 
			
		||||
import type { CancelablePromise } from '../core/CancelablePromise';
 | 
			
		||||
import { OpenAPI } from '../core/OpenAPI';
 | 
			
		||||
import { request as __request } from '../core/request';
 | 
			
		||||
@@ -29,6 +31,26 @@ export class DealService {
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Quick Create
 | 
			
		||||
     * @returns DealCreateResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static quickCreateDealQuickCreatePost({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: DealQuickCreateRequest,
 | 
			
		||||
    }): CancelablePromise<DealCreateResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/deal/quickCreate',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Change Status
 | 
			
		||||
     * @returns DealChangeStatusResponse Successful Response
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,53 @@
 | 
			
		||||
import {FC, useState} from "react";
 | 
			
		||||
 | 
			
		||||
import styles from './CreateDealButton.module.css';
 | 
			
		||||
import {Button, rem, Text, TextInput, Transition} from '@mantine/core';
 | 
			
		||||
import {Text, Transition} from '@mantine/core';
 | 
			
		||||
import CreateDealFrom from "../CreateDealForm/CreateDealFrom.tsx";
 | 
			
		||||
import {DealService} from "../../../client";
 | 
			
		||||
import {dateWithoutTimezone} from "../../../shared/lib/utils.ts";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    onClick: () => void;
 | 
			
		||||
}
 | 
			
		||||
const CreateDealButton: FC<Props> = ({onClick}) => {
 | 
			
		||||
    const [isCreating, setIsCreating] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const [isTransitionEnded, setIsTransitionEnded] = useState(true);
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={styles['container']}
 | 
			
		||||
             onClick={() => {
 | 
			
		||||
                 if (isCreating) return;
 | 
			
		||||
                 setIsCreating(prevState => !prevState)
 | 
			
		||||
                 setIsTransitionEnded(false);
 | 
			
		||||
             }}
 | 
			
		||||
        >
 | 
			
		||||
            {(!isCreating && isTransitionEnded) &&
 | 
			
		||||
                <Text>Быстрое добавление</Text>
 | 
			
		||||
            }
 | 
			
		||||
            <Transition
 | 
			
		||||
                mounted={isCreating}
 | 
			
		||||
                transition={"scale-y"}
 | 
			
		||||
                onExited={() => setIsTransitionEnded(true)}
 | 
			
		||||
            >
 | 
			
		||||
                {(styles) => (
 | 
			
		||||
                    <div style={styles}>
 | 
			
		||||
                        <CreateDealFrom
 | 
			
		||||
                            onCancel={() => {
 | 
			
		||||
                                setIsCreating(false)
 | 
			
		||||
                            }}
 | 
			
		||||
                            onSubmit={(quickDeal) => {
 | 
			
		||||
                                console.log(quickDeal);
 | 
			
		||||
                                DealService.quickCreateDealQuickCreatePost({
 | 
			
		||||
                                    requestBody: {
 | 
			
		||||
                                        ...quickDeal,
 | 
			
		||||
                                        acceptance_date: dateWithoutTimezone(quickDeal.acceptance_date)
 | 
			
		||||
                                    }
 | 
			
		||||
                                })
 | 
			
		||||
                            }}
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
                )}
 | 
			
		||||
            </Transition>
 | 
			
		||||
 | 
			
		||||
            <Text>Быстрое добавление</Text>
 | 
			
		||||
            <CreateDealFrom
 | 
			
		||||
                onCancel={() => {
 | 
			
		||||
                }}
 | 
			
		||||
                onSubmit={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,8 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
			
		||||
    const form = useForm({
 | 
			
		||||
        initialValues: {
 | 
			
		||||
            name: '',
 | 
			
		||||
            clientName: '',
 | 
			
		||||
            clientAddress: '',
 | 
			
		||||
            client_name: '',
 | 
			
		||||
            client_address: '',
 | 
			
		||||
            comment: '',
 | 
			
		||||
            acceptance_date: new Date()
 | 
			
		||||
        }
 | 
			
		||||
@@ -23,7 +23,7 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <form
 | 
			
		||||
            style={{width: '100%'}}
 | 
			
		||||
            onSubmit={form.onSubmit((values) => console.log(values))}
 | 
			
		||||
            onSubmit={form.onSubmit((values) => onSubmit(values))}
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
            <div style={{
 | 
			
		||||
@@ -43,10 +43,9 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
			
		||||
                <div className={styles['inputs']}>
 | 
			
		||||
                    <ClientSelect
 | 
			
		||||
                        withAddress
 | 
			
		||||
                        nameRestProps={form.getInputProps('clientName')}
 | 
			
		||||
                        addressRestProps={form.getInputProps('clientAddress')}
 | 
			
		||||
                        onSelect={() => {
 | 
			
		||||
                        }}/>
 | 
			
		||||
                        nameRestProps={form.getInputProps('client_name')}
 | 
			
		||||
                        addressRestProps={form.getInputProps('client_address')}
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div className={styles['inputs']}>
 | 
			
		||||
@@ -61,6 +60,7 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
			
		||||
                <div className={styles['inputs']}>
 | 
			
		||||
                    <DateTimePicker
 | 
			
		||||
                        placeholder={'Дата приемки'}
 | 
			
		||||
                        {...form.getInputProps('acceptance_date')}
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ const ClientSelect: FC<Props> = ({onSelect, addressRestProps, nameRestProps, wit
 | 
			
		||||
            {withAddress &&
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    placeholder={'Клиент: адрес'}
 | 
			
		||||
                    value={selectedClient?.address}
 | 
			
		||||
                    value={selectedClient?.address || ''}
 | 
			
		||||
                    onChange={event => {
 | 
			
		||||
                        selectClient(prevState => prevState && {...prevState, address: event.target.value})
 | 
			
		||||
                    }}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								src/features/uiSlice.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/features/uiSlice.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
 | 
			
		||||
 | 
			
		||||
interface UIState {
 | 
			
		||||
    isLoading: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const initialState: UIState = {
 | 
			
		||||
    isLoading: false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const uiSlice = createSlice({
 | 
			
		||||
        name: 'ui',
 | 
			
		||||
        initialState,
 | 
			
		||||
        reducers: {
 | 
			
		||||
            setIsLoading: (state, action: PayloadAction<boolean>) => {
 | 
			
		||||
                state.isLoading = action.payload;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
export default uiSlice.reducer;
 | 
			
		||||
export const {setIsLoading} = uiSlice.actions;
 | 
			
		||||
@@ -1,42 +1,49 @@
 | 
			
		||||
import {FC} from "react";
 | 
			
		||||
import {FC, useEffect} from "react";
 | 
			
		||||
import styles from './LeadsPage.module.css';
 | 
			
		||||
import Board from "../../../components/Dnd/Board/Board.tsx";
 | 
			
		||||
import {Button, TextInput} from "@mantine/core";
 | 
			
		||||
import {DragDropContext} from "@hello-pangea/dnd";
 | 
			
		||||
import ClientSelect from "../../../components/Selects/ClientSelect/ClientSelect.tsx";
 | 
			
		||||
import {DateTimePicker} from "@mantine/dates";
 | 
			
		||||
import {useAppDispatch} from "../../../redux/store.ts";
 | 
			
		||||
import {setIsLoading} from "../../../features/uiSlice.ts";
 | 
			
		||||
 | 
			
		||||
export const LeadsPage: FC = () => {
 | 
			
		||||
    const dispatch = useAppDispatch();
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        dispatch(setIsLoading(true));
 | 
			
		||||
    }, []);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={styles['container']}>
 | 
			
		||||
            <div className={styles['header']}>
 | 
			
		||||
        <>
 | 
			
		||||
            <div className={styles['container']}>
 | 
			
		||||
                <div className={styles['header']}>
 | 
			
		||||
                    <TextInput
 | 
			
		||||
                        radius={0}
 | 
			
		||||
                        placeholder={"Поиск и фильтры"}
 | 
			
		||||
                        size={"xl"}
 | 
			
		||||
                        className={styles['header-input']}
 | 
			
		||||
                    />
 | 
			
		||||
                    <Button
 | 
			
		||||
                        radius={0}
 | 
			
		||||
                        color={"gray"}
 | 
			
		||||
                        variant={'default'}
 | 
			
		||||
                        className={styles['header-button']}
 | 
			
		||||
                    >Поиск</Button>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className={styles['boards']}>
 | 
			
		||||
                    <DragDropContext onDragEnd={() => {
 | 
			
		||||
                    }}>
 | 
			
		||||
                        <Board title={"Ожидает приемки"} withCreateButton droppableId={"AWAITING_ACCEPTANCE"}/>
 | 
			
		||||
                        <Board title={"Упаковка"} droppableId={"PACKAGING"}/>
 | 
			
		||||
                        <Board title={"Ожидает отгрузки"} droppableId={"AWAITING_SHIPMENT"}/>
 | 
			
		||||
                        <Board title={"Ожидает оплаты"} droppableId={"AWAITING_PAYMENT"}/>
 | 
			
		||||
                        <Board title={"Завершена"} droppableId={"COMPLETED"}/>
 | 
			
		||||
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    radius={0}
 | 
			
		||||
                    placeholder={"Поиск и фильтры"}
 | 
			
		||||
                    size={"xl"}
 | 
			
		||||
                    className={styles['header-input']}
 | 
			
		||||
                />
 | 
			
		||||
                <Button
 | 
			
		||||
                    radius={0}
 | 
			
		||||
                    color={"gray"}
 | 
			
		||||
                    variant={'default'}
 | 
			
		||||
                    className={styles['header-button']}
 | 
			
		||||
                >Поиск</Button>
 | 
			
		||||
                    </DragDropContext>
 | 
			
		||||
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className={styles['boards']}>
 | 
			
		||||
                <DragDropContext onDragEnd={() => {
 | 
			
		||||
                }}>
 | 
			
		||||
                    <Board title={"Ожидает приемки"} withCreateButton droppableId={"AWAITING_ACCEPTANCE"}/>
 | 
			
		||||
                    <Board title={"Упаковка"} droppableId={"PACKAGING"}/>
 | 
			
		||||
                    <Board title={"Ожидает отгрузки"} droppableId={"AWAITING_SHIPMENT"}/>
 | 
			
		||||
                    <Board title={"Ожидает оплаты"} droppableId={"AWAITING_PAYMENT"}/>
 | 
			
		||||
                    <Board title={"Завершена"} droppableId={"COMPLETED"}/>
 | 
			
		||||
        </>
 | 
			
		||||
 | 
			
		||||
                </DragDropContext>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,11 @@ import {useSelector} from "react-redux";
 | 
			
		||||
import {RootState} from "../../redux/store.ts";
 | 
			
		||||
import {OpenAPI} from "../../client";
 | 
			
		||||
import PageWrapper from "../PageWrapper/PageWrapper.tsx";
 | 
			
		||||
import {LoadingOverlay} from "@mantine/core";
 | 
			
		||||
 | 
			
		||||
const RootPage = () => {
 | 
			
		||||
    const authState = useSelector((state: RootState) => state.auth);
 | 
			
		||||
    const uiState = useSelector((state: RootState) => state.ui);
 | 
			
		||||
    const rewriteLocalStorage = () => {
 | 
			
		||||
        const jsonData = JSON.stringify(authState);
 | 
			
		||||
        localStorage.setItem('authState', jsonData);
 | 
			
		||||
@@ -21,13 +23,11 @@ const RootPage = () => {
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={uiState.isLoading}/>
 | 
			
		||||
            <PageWrapper>
 | 
			
		||||
                <Outlet/>
 | 
			
		||||
            </PageWrapper>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        </>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
import {configureStore} from "@reduxjs/toolkit";
 | 
			
		||||
import {useDispatch} from "react-redux";
 | 
			
		||||
import authReducer from '../features/authSlice';
 | 
			
		||||
import uiReducer from '../features/uiSlice';
 | 
			
		||||
 | 
			
		||||
export const store = configureStore({
 | 
			
		||||
    reducer: {
 | 
			
		||||
        auth: authReducer
 | 
			
		||||
        auth: authReducer,
 | 
			
		||||
        ui: uiReducer
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								src/shared/lib/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/shared/lib/utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
export const dateWithoutTimezone = (date: Date) => {
 | 
			
		||||
    const tzoffset = date.getTimezoneOffset() * 60000; //offset in milliseconds
 | 
			
		||||
    const withoutTimezone = new Date(date.valueOf() - tzoffset)
 | 
			
		||||
        .toISOString()
 | 
			
		||||
        .slice(0, -1);
 | 
			
		||||
    return withoutTimezone;
 | 
			
		||||
};
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
import {Client} from "./Client.ts";
 | 
			
		||||
 | 
			
		||||
export type QuickDeal = {
 | 
			
		||||
    name: string;
 | 
			
		||||
    client: Client
 | 
			
		||||
    comment: string;
 | 
			
		||||
    acceptance_date: string;
 | 
			
		||||
    name: string
 | 
			
		||||
    client_name: string
 | 
			
		||||
    client_address: string
 | 
			
		||||
    comment:string
 | 
			
		||||
    acceptance_date: Date
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user