othr
This commit is contained in:
@@ -12,6 +12,8 @@ export type { AuthLoginResponse } from './models/AuthLoginResponse';
|
|||||||
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
|
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
|
||||||
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
|
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
|
||||||
export type { DealCreateRequest } from './models/DealCreateRequest';
|
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 { HTTPValidationError } from './models/HTTPValidationError';
|
||||||
export type { ValidationError } from './models/ValidationError';
|
export type { ValidationError } from './models/ValidationError';
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
|
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
|
||||||
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
|
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
|
||||||
import type { DealCreateRequest } from '../models/DealCreateRequest';
|
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 type { CancelablePromise } from '../core/CancelablePromise';
|
||||||
import { OpenAPI } from '../core/OpenAPI';
|
import { OpenAPI } from '../core/OpenAPI';
|
||||||
import { request as __request } from '../core/request';
|
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
|
* Change Status
|
||||||
* @returns DealChangeStatusResponse Successful Response
|
* @returns DealChangeStatusResponse Successful Response
|
||||||
|
|||||||
@@ -1,30 +1,53 @@
|
|||||||
import {FC, useState} from "react";
|
import {FC, useState} from "react";
|
||||||
|
|
||||||
import styles from './CreateDealButton.module.css';
|
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 CreateDealFrom from "../CreateDealForm/CreateDealFrom.tsx";
|
||||||
|
import {DealService} from "../../../client";
|
||||||
|
import {dateWithoutTimezone} from "../../../shared/lib/utils.ts";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
const CreateDealButton: FC<Props> = ({onClick}) => {
|
const CreateDealButton: FC<Props> = ({onClick}) => {
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
const [isCreating, setIsCreating] = useState(false);
|
||||||
|
const [isTransitionEnded, setIsTransitionEnded] = useState(true);
|
||||||
return (
|
return (
|
||||||
<div className={styles['container']}
|
<div className={styles['container']}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isCreating) return;
|
if (isCreating) return;
|
||||||
setIsCreating(prevState => !prevState)
|
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>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
|
|||||||
const form = useForm({
|
const form = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
name: '',
|
name: '',
|
||||||
clientName: '',
|
client_name: '',
|
||||||
clientAddress: '',
|
client_address: '',
|
||||||
comment: '',
|
comment: '',
|
||||||
acceptance_date: new Date()
|
acceptance_date: new Date()
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
|
|||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
style={{width: '100%'}}
|
style={{width: '100%'}}
|
||||||
onSubmit={form.onSubmit((values) => console.log(values))}
|
onSubmit={form.onSubmit((values) => onSubmit(values))}
|
||||||
>
|
>
|
||||||
|
|
||||||
<div style={{
|
<div style={{
|
||||||
@@ -43,10 +43,9 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
|
|||||||
<div className={styles['inputs']}>
|
<div className={styles['inputs']}>
|
||||||
<ClientSelect
|
<ClientSelect
|
||||||
withAddress
|
withAddress
|
||||||
nameRestProps={form.getInputProps('clientName')}
|
nameRestProps={form.getInputProps('client_name')}
|
||||||
addressRestProps={form.getInputProps('clientAddress')}
|
addressRestProps={form.getInputProps('client_address')}
|
||||||
onSelect={() => {
|
/>
|
||||||
}}/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles['inputs']}>
|
<div className={styles['inputs']}>
|
||||||
@@ -61,6 +60,7 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
|
|||||||
<div className={styles['inputs']}>
|
<div className={styles['inputs']}>
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
placeholder={'Дата приемки'}
|
placeholder={'Дата приемки'}
|
||||||
|
{...form.getInputProps('acceptance_date')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const ClientSelect: FC<Props> = ({onSelect, addressRestProps, nameRestProps, wit
|
|||||||
{withAddress &&
|
{withAddress &&
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={'Клиент: адрес'}
|
placeholder={'Клиент: адрес'}
|
||||||
value={selectedClient?.address}
|
value={selectedClient?.address || ''}
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
selectClient(prevState => prevState && {...prevState, address: event.target.value})
|
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 styles from './LeadsPage.module.css';
|
||||||
import Board from "../../../components/Dnd/Board/Board.tsx";
|
import Board from "../../../components/Dnd/Board/Board.tsx";
|
||||||
import {Button, TextInput} from "@mantine/core";
|
import {Button, TextInput} from "@mantine/core";
|
||||||
import {DragDropContext} from "@hello-pangea/dnd";
|
import {DragDropContext} from "@hello-pangea/dnd";
|
||||||
import ClientSelect from "../../../components/Selects/ClientSelect/ClientSelect.tsx";
|
import {useAppDispatch} from "../../../redux/store.ts";
|
||||||
import {DateTimePicker} from "@mantine/dates";
|
import {setIsLoading} from "../../../features/uiSlice.ts";
|
||||||
|
|
||||||
export const LeadsPage: FC = () => {
|
export const LeadsPage: FC = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(setIsLoading(true));
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
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
|
</DragDropContext>
|
||||||
radius={0}
|
|
||||||
placeholder={"Поиск и фильтры"}
|
</div>
|
||||||
size={"xl"}
|
|
||||||
className={styles['header-input']}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
radius={0}
|
|
||||||
color={"gray"}
|
|
||||||
variant={'default'}
|
|
||||||
className={styles['header-button']}
|
|
||||||
>Поиск</Button>
|
|
||||||
</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 {RootState} from "../../redux/store.ts";
|
||||||
import {OpenAPI} from "../../client";
|
import {OpenAPI} from "../../client";
|
||||||
import PageWrapper from "../PageWrapper/PageWrapper.tsx";
|
import PageWrapper from "../PageWrapper/PageWrapper.tsx";
|
||||||
|
import {LoadingOverlay} from "@mantine/core";
|
||||||
|
|
||||||
const RootPage = () => {
|
const RootPage = () => {
|
||||||
const authState = useSelector((state: RootState) => state.auth);
|
const authState = useSelector((state: RootState) => state.auth);
|
||||||
|
const uiState = useSelector((state: RootState) => state.ui);
|
||||||
const rewriteLocalStorage = () => {
|
const rewriteLocalStorage = () => {
|
||||||
const jsonData = JSON.stringify(authState);
|
const jsonData = JSON.stringify(authState);
|
||||||
localStorage.setItem('authState', jsonData);
|
localStorage.setItem('authState', jsonData);
|
||||||
@@ -21,13 +23,11 @@ const RootPage = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<LoadingOverlay visible={uiState.isLoading}/>
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<Outlet/>
|
<Outlet/>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import {configureStore} from "@reduxjs/toolkit";
|
import {configureStore} from "@reduxjs/toolkit";
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
import authReducer from '../features/authSlice';
|
import authReducer from '../features/authSlice';
|
||||||
|
import uiReducer from '../features/uiSlice';
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
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 = {
|
export type QuickDeal = {
|
||||||
name: string;
|
name: string
|
||||||
client: Client
|
client_name: string
|
||||||
comment: string;
|
client_address: string
|
||||||
acceptance_date: string;
|
comment:string
|
||||||
|
acceptance_date: Date
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user