Simplify manager order editing UI
This commit is contained in:
@@ -71,7 +71,7 @@ function currentUnitPrice(item: OrderItemView) {
|
||||
return item.unitPrice ?? null;
|
||||
}
|
||||
|
||||
return parseMoneyDraft(props.unitPriceDrafts?.[item.id], item.unitPrice);
|
||||
return parseMoneyDraft(props.unitPriceDrafts?.[item.id]);
|
||||
}
|
||||
|
||||
function currentLineTotal(item: OrderItemView) {
|
||||
|
||||
@@ -47,11 +47,6 @@ export type AuthSession = {
|
||||
user: User;
|
||||
};
|
||||
|
||||
export type BlockOrderInput = {
|
||||
orderId: Scalars['ID']['input'];
|
||||
reason: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type BonusTransaction = {
|
||||
__typename?: 'BonusTransaction';
|
||||
amount: Scalars['Float']['output'];
|
||||
@@ -279,18 +274,16 @@ export type Mutation = {
|
||||
acceptInvitation: User;
|
||||
addBonusTransaction: BonusTransaction;
|
||||
addProductToCart: Cart;
|
||||
blockOrder: Order;
|
||||
clearCart: Cart;
|
||||
clientReviewOrder: Order;
|
||||
completeOrder: Order;
|
||||
connectMessenger: MessengerConnection;
|
||||
consumeLoginToken: AuthSession;
|
||||
createInvitation: Invitation;
|
||||
createMyDeliveryAddress: DeliveryAddress;
|
||||
createReferral: ReferralLink;
|
||||
deleteMyDeliveryAddress: Scalars['Boolean']['output'];
|
||||
managerFinalizeOrder: Order;
|
||||
managerSetOrderOffer: Order;
|
||||
managerSetOrderStatus: Order;
|
||||
registerSelf: RegistrationRequest;
|
||||
removeCartItem: Cart;
|
||||
requestLoginCode: AuthCodeRequestResult;
|
||||
@@ -300,7 +293,6 @@ export type Mutation = {
|
||||
sendTestMessengerMessage: MessengerDispatchResult;
|
||||
setCartDeliveryAddress: Cart;
|
||||
setMyDefaultDeliveryAddress: DeliveryAddress;
|
||||
startOrderWork: Order;
|
||||
submitCalculationOrder: Order;
|
||||
submitReadyOrder: Order;
|
||||
updateCartItemQuantity: Cart;
|
||||
@@ -324,22 +316,12 @@ export type MutationAddProductToCartArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationBlockOrderArgs = {
|
||||
input: BlockOrderInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationClientReviewOrderArgs = {
|
||||
decision: Decision;
|
||||
orderId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationCompleteOrderArgs = {
|
||||
orderId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationConnectMessengerArgs = {
|
||||
input: ConnectMessengerInput;
|
||||
};
|
||||
@@ -370,14 +352,14 @@ export type MutationDeleteMyDeliveryAddressArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationManagerFinalizeOrderArgs = {
|
||||
decision: Decision;
|
||||
orderId: Scalars['ID']['input'];
|
||||
export type MutationManagerSetOrderOfferArgs = {
|
||||
input: SetOrderOfferInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationManagerSetOrderOfferArgs = {
|
||||
input: SetOrderOfferInput;
|
||||
export type MutationManagerSetOrderStatusArgs = {
|
||||
orderId: Scalars['ID']['input'];
|
||||
status: OrderStatus;
|
||||
};
|
||||
|
||||
|
||||
@@ -428,11 +410,6 @@ export type MutationSetMyDefaultDeliveryAddressArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationStartOrderWorkArgs = {
|
||||
orderId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationSubmitCalculationOrderArgs = {
|
||||
input: SubmitCalculationOrderInput;
|
||||
};
|
||||
@@ -501,7 +478,7 @@ export type OrderItem = {
|
||||
|
||||
export type OrderItemPriceInput = {
|
||||
itemId: Scalars['ID']['input'];
|
||||
unitPrice: Scalars['Float']['input'];
|
||||
unitPrice?: InputMaybe<Scalars['Float']['input']>;
|
||||
};
|
||||
|
||||
export enum OrderKind {
|
||||
@@ -701,7 +678,7 @@ export type RewardWithdrawalRequest = {
|
||||
};
|
||||
|
||||
export type SetOrderOfferInput = {
|
||||
deliveryFee: Scalars['Float']['input'];
|
||||
deliveryFee?: InputMaybe<Scalars['Float']['input']>;
|
||||
deliveryTerms: Scalars['String']['input'];
|
||||
itemPrices: Array<OrderItemPriceInput>;
|
||||
orderId: Scalars['ID']['input'];
|
||||
@@ -856,20 +833,6 @@ export type AddBonusTransactionMutationVariables = Exact<{
|
||||
|
||||
export type AddBonusTransactionMutation = { __typename?: 'Mutation', addBonusTransaction: { __typename?: 'BonusTransaction', id: string, userId: string, amount: number, reason: string, createdAt: any } };
|
||||
|
||||
export type BlockOrderMutationVariables = Exact<{
|
||||
input: BlockOrderInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type BlockOrderMutation = { __typename?: 'Mutation', blockOrder: { __typename?: 'Order', id: string, status: OrderStatus, blockReason?: string | null } };
|
||||
|
||||
export type CompleteOrderMutationVariables = Exact<{
|
||||
orderId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type CompleteOrderMutation = { __typename?: 'Mutation', completeOrder: { __typename?: 'Order', id: string, status: OrderStatus } };
|
||||
|
||||
export type CreateInvitationMutationVariables = Exact<{
|
||||
input: CreateInvitationInput;
|
||||
}>;
|
||||
@@ -896,14 +859,6 @@ export type ManagerBonusBalancesQueryVariables = Exact<{ [key: string]: never; }
|
||||
|
||||
export type ManagerBonusBalancesQuery = { __typename?: 'Query', managerBonusBalances: Array<{ __typename?: 'ManagerBonusBalance', userId: string, email: string, fullName: string, companyName?: string | null, balance: number, pendingWithdrawalAmount: number, transactionsCount: number }> };
|
||||
|
||||
export type ManagerFinalizeOrderMutationVariables = Exact<{
|
||||
orderId: Scalars['ID']['input'];
|
||||
decision: Decision;
|
||||
}>;
|
||||
|
||||
|
||||
export type ManagerFinalizeOrderMutation = { __typename?: 'Mutation', managerFinalizeOrder: { __typename?: 'Order', id: string, status: OrderStatus, managerApproved?: boolean | null } };
|
||||
|
||||
export type ManagerOrdersQueryVariables = Exact<{
|
||||
status?: InputMaybe<OrderStatus>;
|
||||
customerId?: InputMaybe<Scalars['ID']['input']>;
|
||||
@@ -917,6 +872,14 @@ export type ManagerReferralLinksQueryVariables = Exact<{ [key: string]: never; }
|
||||
|
||||
export type ManagerReferralLinksQuery = { __typename?: 'Query', managerReferralLinks: Array<{ __typename?: 'ManagerReferralLink', id: string, referrerId: string, referrerName: string, referrerEmail: string, referrerCompanyName?: string | null, refereeId: string, refereeName: string, refereeEmail: string, refereeCompanyName?: string | null, createdById: string, bonusPercent: number, createdAt: any }> };
|
||||
|
||||
export type ManagerSetOrderStatusMutationVariables = Exact<{
|
||||
orderId: Scalars['ID']['input'];
|
||||
status: OrderStatus;
|
||||
}>;
|
||||
|
||||
|
||||
export type ManagerSetOrderStatusMutation = { __typename?: 'Mutation', managerSetOrderStatus: { __typename?: 'Order', id: string, status: OrderStatus } };
|
||||
|
||||
export type ManagerUsersDetailQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -967,13 +930,6 @@ export type ManagerSetOrderOfferMutationVariables = Exact<{
|
||||
|
||||
export type ManagerSetOrderOfferMutation = { __typename?: 'Mutation', managerSetOrderOffer: { __typename?: 'Order', id: string, code: string, status: OrderStatus, deliveryTerms?: string | null, deliveryFee?: number | null, totalPrice?: number | null, items: Array<{ __typename?: 'OrderItem', id: string, unitPrice?: number | null, lineTotal?: number | null }> } };
|
||||
|
||||
export type StartOrderWorkMutationVariables = Exact<{
|
||||
orderId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type StartOrderWorkMutation = { __typename?: 'Mutation', startOrderWork: { __typename?: 'Order', id: string, status: OrderStatus } };
|
||||
|
||||
export type ManagerNotificationHistoryQueryVariables = Exact<{
|
||||
userId: Scalars['ID']['input'];
|
||||
channel: MessengerType;
|
||||
@@ -1580,67 +1536,6 @@ export function useAddBonusTransactionMutation(options: VueApolloComposable.UseM
|
||||
return VueApolloComposable.useMutation<AddBonusTransactionMutation, AddBonusTransactionMutationVariables>(AddBonusTransactionDocument, options);
|
||||
}
|
||||
export type AddBonusTransactionMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<AddBonusTransactionMutation, AddBonusTransactionMutationVariables>;
|
||||
export const BlockOrderDocument = gql`
|
||||
mutation BlockOrder($input: BlockOrderInput!) {
|
||||
blockOrder(input: $input) {
|
||||
id
|
||||
status
|
||||
blockReason
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useBlockOrderMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useBlockOrderMutation` within a Vue component and pass it any options that fit your needs.
|
||||
* When your component renders, `useBlockOrderMutation` returns an object that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - Several other properties: https://v4.apollo.vuejs.org/api/use-mutation.html#return
|
||||
*
|
||||
* @param options that will be passed into the mutation, supported options are listed on: https://v4.apollo.vuejs.org/guide-composable/mutation.html#options;
|
||||
*
|
||||
* @example
|
||||
* const { mutate, loading, error, onDone } = useBlockOrderMutation({
|
||||
* variables: {
|
||||
* input: // value for 'input'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useBlockOrderMutation(options: VueApolloComposable.UseMutationOptions<BlockOrderMutation, BlockOrderMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<BlockOrderMutation, BlockOrderMutationVariables>> = {}) {
|
||||
return VueApolloComposable.useMutation<BlockOrderMutation, BlockOrderMutationVariables>(BlockOrderDocument, options);
|
||||
}
|
||||
export type BlockOrderMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<BlockOrderMutation, BlockOrderMutationVariables>;
|
||||
export const CompleteOrderDocument = gql`
|
||||
mutation CompleteOrder($orderId: ID!) {
|
||||
completeOrder(orderId: $orderId) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useCompleteOrderMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useCompleteOrderMutation` within a Vue component and pass it any options that fit your needs.
|
||||
* When your component renders, `useCompleteOrderMutation` returns an object that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - Several other properties: https://v4.apollo.vuejs.org/api/use-mutation.html#return
|
||||
*
|
||||
* @param options that will be passed into the mutation, supported options are listed on: https://v4.apollo.vuejs.org/guide-composable/mutation.html#options;
|
||||
*
|
||||
* @example
|
||||
* const { mutate, loading, error, onDone } = useCompleteOrderMutation({
|
||||
* variables: {
|
||||
* orderId: // value for 'orderId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useCompleteOrderMutation(options: VueApolloComposable.UseMutationOptions<CompleteOrderMutation, CompleteOrderMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<CompleteOrderMutation, CompleteOrderMutationVariables>> = {}) {
|
||||
return VueApolloComposable.useMutation<CompleteOrderMutation, CompleteOrderMutationVariables>(CompleteOrderDocument, options);
|
||||
}
|
||||
export type CompleteOrderMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<CompleteOrderMutation, CompleteOrderMutationVariables>;
|
||||
export const CreateInvitationDocument = gql`
|
||||
mutation CreateInvitation($input: CreateInvitationInput!) {
|
||||
createInvitation(input: $input) {
|
||||
@@ -1810,38 +1705,6 @@ export function useManagerBonusBalancesLazyQuery(options: VueApolloComposable.Us
|
||||
return VueApolloComposable.useLazyQuery<ManagerBonusBalancesQuery, ManagerBonusBalancesQueryVariables>(ManagerBonusBalancesDocument, {}, options);
|
||||
}
|
||||
export type ManagerBonusBalancesQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<ManagerBonusBalancesQuery, ManagerBonusBalancesQueryVariables>;
|
||||
export const ManagerFinalizeOrderDocument = gql`
|
||||
mutation ManagerFinalizeOrder($orderId: ID!, $decision: Decision!) {
|
||||
managerFinalizeOrder(orderId: $orderId, decision: $decision) {
|
||||
id
|
||||
status
|
||||
managerApproved
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useManagerFinalizeOrderMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useManagerFinalizeOrderMutation` within a Vue component and pass it any options that fit your needs.
|
||||
* When your component renders, `useManagerFinalizeOrderMutation` returns an object that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - Several other properties: https://v4.apollo.vuejs.org/api/use-mutation.html#return
|
||||
*
|
||||
* @param options that will be passed into the mutation, supported options are listed on: https://v4.apollo.vuejs.org/guide-composable/mutation.html#options;
|
||||
*
|
||||
* @example
|
||||
* const { mutate, loading, error, onDone } = useManagerFinalizeOrderMutation({
|
||||
* variables: {
|
||||
* orderId: // value for 'orderId'
|
||||
* decision: // value for 'decision'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useManagerFinalizeOrderMutation(options: VueApolloComposable.UseMutationOptions<ManagerFinalizeOrderMutation, ManagerFinalizeOrderMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ManagerFinalizeOrderMutation, ManagerFinalizeOrderMutationVariables>> = {}) {
|
||||
return VueApolloComposable.useMutation<ManagerFinalizeOrderMutation, ManagerFinalizeOrderMutationVariables>(ManagerFinalizeOrderDocument, options);
|
||||
}
|
||||
export type ManagerFinalizeOrderMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ManagerFinalizeOrderMutation, ManagerFinalizeOrderMutationVariables>;
|
||||
export const ManagerOrdersDocument = gql`
|
||||
query ManagerOrders($status: OrderStatus, $customerId: ID) {
|
||||
managerOrders(status: $status, customerId: $customerId) {
|
||||
@@ -1927,6 +1790,37 @@ export function useManagerReferralLinksLazyQuery(options: VueApolloComposable.Us
|
||||
return VueApolloComposable.useLazyQuery<ManagerReferralLinksQuery, ManagerReferralLinksQueryVariables>(ManagerReferralLinksDocument, {}, options);
|
||||
}
|
||||
export type ManagerReferralLinksQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<ManagerReferralLinksQuery, ManagerReferralLinksQueryVariables>;
|
||||
export const ManagerSetOrderStatusDocument = gql`
|
||||
mutation ManagerSetOrderStatus($orderId: ID!, $status: OrderStatus!) {
|
||||
managerSetOrderStatus(orderId: $orderId, status: $status) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useManagerSetOrderStatusMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useManagerSetOrderStatusMutation` within a Vue component and pass it any options that fit your needs.
|
||||
* When your component renders, `useManagerSetOrderStatusMutation` returns an object that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - Several other properties: https://v4.apollo.vuejs.org/api/use-mutation.html#return
|
||||
*
|
||||
* @param options that will be passed into the mutation, supported options are listed on: https://v4.apollo.vuejs.org/guide-composable/mutation.html#options;
|
||||
*
|
||||
* @example
|
||||
* const { mutate, loading, error, onDone } = useManagerSetOrderStatusMutation({
|
||||
* variables: {
|
||||
* orderId: // value for 'orderId'
|
||||
* status: // value for 'status'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useManagerSetOrderStatusMutation(options: VueApolloComposable.UseMutationOptions<ManagerSetOrderStatusMutation, ManagerSetOrderStatusMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ManagerSetOrderStatusMutation, ManagerSetOrderStatusMutationVariables>> = {}) {
|
||||
return VueApolloComposable.useMutation<ManagerSetOrderStatusMutation, ManagerSetOrderStatusMutationVariables>(ManagerSetOrderStatusDocument, options);
|
||||
}
|
||||
export type ManagerSetOrderStatusMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ManagerSetOrderStatusMutation, ManagerSetOrderStatusMutationVariables>;
|
||||
export const ManagerUsersDetailDocument = gql`
|
||||
query ManagerUsersDetail {
|
||||
managerUsers {
|
||||
@@ -2232,36 +2126,6 @@ export function useManagerSetOrderOfferMutation(options: VueApolloComposable.Use
|
||||
return VueApolloComposable.useMutation<ManagerSetOrderOfferMutation, ManagerSetOrderOfferMutationVariables>(ManagerSetOrderOfferDocument, options);
|
||||
}
|
||||
export type ManagerSetOrderOfferMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ManagerSetOrderOfferMutation, ManagerSetOrderOfferMutationVariables>;
|
||||
export const StartOrderWorkDocument = gql`
|
||||
mutation StartOrderWork($orderId: ID!) {
|
||||
startOrderWork(orderId: $orderId) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useStartOrderWorkMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useStartOrderWorkMutation` within a Vue component and pass it any options that fit your needs.
|
||||
* When your component renders, `useStartOrderWorkMutation` returns an object that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - Several other properties: https://v4.apollo.vuejs.org/api/use-mutation.html#return
|
||||
*
|
||||
* @param options that will be passed into the mutation, supported options are listed on: https://v4.apollo.vuejs.org/guide-composable/mutation.html#options;
|
||||
*
|
||||
* @example
|
||||
* const { mutate, loading, error, onDone } = useStartOrderWorkMutation({
|
||||
* variables: {
|
||||
* orderId: // value for 'orderId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useStartOrderWorkMutation(options: VueApolloComposable.UseMutationOptions<StartOrderWorkMutation, StartOrderWorkMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<StartOrderWorkMutation, StartOrderWorkMutationVariables>> = {}) {
|
||||
return VueApolloComposable.useMutation<StartOrderWorkMutation, StartOrderWorkMutationVariables>(StartOrderWorkDocument, options);
|
||||
}
|
||||
export type StartOrderWorkMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<StartOrderWorkMutation, StartOrderWorkMutationVariables>;
|
||||
export const ManagerNotificationHistoryDocument = gql`
|
||||
query ManagerNotificationHistory($userId: ID!, $channel: MessengerType!, $limit: Int) {
|
||||
managerNotificationHistory(userId: $userId, channel: $channel, limit: $limit) {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { useMutation, useQuery } from '@vue/apollo-composable';
|
||||
import {
|
||||
CompleteOrderDocument,
|
||||
Decision,
|
||||
ManagerFinalizeOrderDocument,
|
||||
ManagerSetOrderOfferDocument,
|
||||
ManagerSetOrderStatusDocument,
|
||||
OrderStatus,
|
||||
OrderDetailDocument,
|
||||
StartOrderWorkDocument,
|
||||
type OrderDetailQuery,
|
||||
} from '~/composables/graphql/generated';
|
||||
import {
|
||||
@@ -24,9 +22,8 @@ const route = useRoute();
|
||||
const orderId = computed(() => String(route.params.id || ''));
|
||||
|
||||
type ManagerOrderItem = NonNullable<OrderDetailQuery['order']>;
|
||||
type StatusAction = 'APPROVE' | 'REJECT' | 'START' | 'COMPLETE';
|
||||
type StatusActionOption = {
|
||||
value: StatusAction;
|
||||
type StatusOption = {
|
||||
value: OrderStatus;
|
||||
label: string;
|
||||
};
|
||||
|
||||
@@ -34,10 +31,8 @@ const orderQuery = useQuery(OrderDetailDocument, () => ({
|
||||
id: orderId.value,
|
||||
}));
|
||||
|
||||
const completeOrderMutation = useMutation(CompleteOrderDocument);
|
||||
const finalizeOrderMutation = useMutation(ManagerFinalizeOrderDocument);
|
||||
const startWorkMutation = useMutation(StartOrderWorkDocument);
|
||||
const setOfferMutation = useMutation(ManagerSetOrderOfferDocument);
|
||||
const setOrderStatusMutation = useMutation(ManagerSetOrderStatusDocument);
|
||||
|
||||
const itemPriceDrafts = reactive<Record<string, string>>({});
|
||||
const deliveryTermsDraft = ref('');
|
||||
@@ -46,7 +41,7 @@ const editingPriceItemId = ref<string | null>(null);
|
||||
const editingDeliveryTerms = ref(false);
|
||||
const editingDeliveryFee = ref(false);
|
||||
const editingStatus = ref(false);
|
||||
const statusActionDraft = ref<StatusAction | ''>('');
|
||||
const statusDraft = ref<OrderStatus | ''>('');
|
||||
const autosavePending = ref(false);
|
||||
const statusMutationPending = ref(false);
|
||||
let autosaveTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -64,7 +59,7 @@ watch(
|
||||
editingDeliveryTerms.value = false;
|
||||
editingDeliveryFee.value = false;
|
||||
editingStatus.value = false;
|
||||
statusActionDraft.value = '';
|
||||
statusDraft.value = '';
|
||||
|
||||
for (const key of Object.keys(itemPriceDrafts)) {
|
||||
delete itemPriceDrafts[key];
|
||||
@@ -101,63 +96,22 @@ function parseMoneyDraft(value: string) {
|
||||
}
|
||||
|
||||
const draftDeliveryTerms = computed(() => deliveryTermsDraft.value.trim() || currentOrder.value?.deliveryTerms || null);
|
||||
const draftDeliveryFee = computed(() => parseMoneyDraft(deliveryFeeDraft.value) ?? currentOrder.value?.deliveryFee ?? null);
|
||||
const canEditOffer = computed(() => (
|
||||
currentOrder.value != null
|
||||
&& ['NEW', 'MANAGER_PROCESSING', 'WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(currentOrder.value.status)
|
||||
));
|
||||
const draftDeliveryFee = computed(() => parseMoneyDraft(deliveryFeeDraft.value));
|
||||
const canEditOffer = computed(() => currentOrder.value != null);
|
||||
const activePriceItemIds = computed(() => (
|
||||
editingPriceItemId.value ? [editingPriceItemId.value] : []
|
||||
));
|
||||
const managerStatusSummary = computed(() => {
|
||||
if (!currentOrder.value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (['NEW', 'MANAGER_PROCESSING'].includes(currentOrder.value.status)) {
|
||||
return 'Заполните цены по позициям и логистике. После этого заказ можно перевести в предложение.';
|
||||
}
|
||||
|
||||
if (['WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(currentOrder.value.status)) {
|
||||
return 'Предложение уже собрано. Следующий шаг для менеджера: перевести заказ в работу или остановить его.';
|
||||
}
|
||||
|
||||
if (currentOrder.value.status === 'IN_PROGRESS') {
|
||||
return 'Заказ уже в работе. После исполнения его можно завершить.';
|
||||
}
|
||||
|
||||
if (currentOrder.value.status === 'COMPLETED') {
|
||||
return 'Заказ завершён и больше не редактируется.';
|
||||
}
|
||||
|
||||
return 'Заказ остановлен. Если нужно продолжить работу, сначала поправьте условия и затем снова переведите его в предложение.';
|
||||
});
|
||||
const statusActions = computed<StatusActionOption[]>(() => {
|
||||
if (!currentOrder.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const options: StatusActionOption[] = [];
|
||||
|
||||
if (offerReady.value && ['NEW', 'MANAGER_PROCESSING', 'MANAGER_BLOCKED', 'CLIENT_REJECTED', 'MANAGER_REJECTED'].includes(currentOrder.value.status)) {
|
||||
options.push({ value: 'APPROVE', label: 'Предложение' });
|
||||
}
|
||||
|
||||
if (['NEW', 'MANAGER_PROCESSING', 'WAITING_DOUBLE_CONFIRM', 'CONFIRMED', 'MANAGER_BLOCKED'].includes(currentOrder.value.status)) {
|
||||
options.push({ value: 'REJECT', label: 'Отклонен' });
|
||||
}
|
||||
|
||||
if (['WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(currentOrder.value.status)) {
|
||||
options.push({ value: 'START', label: 'В работе' });
|
||||
}
|
||||
|
||||
if (currentOrder.value.status === 'IN_PROGRESS') {
|
||||
options.push({ value: 'COMPLETE', label: 'Завершен' });
|
||||
}
|
||||
|
||||
return options;
|
||||
});
|
||||
const canEditStatus = computed(() => statusActions.value.length > 0);
|
||||
const statusOptions: StatusOption[] = [
|
||||
{ value: OrderStatus.New, label: 'Заявка' },
|
||||
{ value: OrderStatus.ManagerProcessing, label: 'В обработке' },
|
||||
{ value: OrderStatus.WaitingDoubleConfirm, label: 'Предложение' },
|
||||
{ value: OrderStatus.Confirmed, label: 'Подтвержден' },
|
||||
{ value: OrderStatus.InProgress, label: 'В работе' },
|
||||
{ value: OrderStatus.Completed, label: 'Завершен' },
|
||||
{ value: OrderStatus.ManagerBlocked, label: 'Пауза' },
|
||||
{ value: OrderStatus.ManagerRejected, label: 'Отклонен менеджером' },
|
||||
{ value: OrderStatus.ClientRejected, label: 'Отклонен клиентом' },
|
||||
];
|
||||
|
||||
const offerSignature = computed(() => {
|
||||
if (!currentOrder.value) {
|
||||
@@ -224,7 +178,7 @@ async function focusElement(selector: string) {
|
||||
}
|
||||
|
||||
async function saveOffer() {
|
||||
if (!currentOrder.value || !offerReady.value || !canEditOffer.value) {
|
||||
if (!currentOrder.value || !canEditOffer.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -235,10 +189,10 @@ async function saveOffer() {
|
||||
orderId: currentOrder.value.id,
|
||||
itemPrices: currentOrder.value.items.map((item) => ({
|
||||
itemId: item.id,
|
||||
unitPrice: parseMoneyDraft(itemPriceDrafts[item.id] ?? '') ?? 0,
|
||||
unitPrice: parseMoneyDraft(itemPriceDrafts[item.id] ?? ''),
|
||||
})),
|
||||
deliveryTerms: deliveryTermsDraft.value.trim(),
|
||||
deliveryFee: parseMoneyDraft(deliveryFeeDraft.value) ?? 0,
|
||||
deliveryFee: parseMoneyDraft(deliveryFeeDraft.value),
|
||||
},
|
||||
});
|
||||
await refetchOrder();
|
||||
@@ -290,24 +244,29 @@ function closeDeliveryFeeEditor() {
|
||||
}
|
||||
|
||||
async function openStatusEditor() {
|
||||
if (!canEditStatus.value || statusMutationPending.value) {
|
||||
if (statusMutationPending.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
editingStatus.value = true;
|
||||
statusActionDraft.value = '';
|
||||
statusDraft.value = currentOrder.value?.status ?? '';
|
||||
await focusElement('[data-manager-status-select]');
|
||||
}
|
||||
|
||||
function closeStatusEditor() {
|
||||
if (!statusMutationPending.value) {
|
||||
editingStatus.value = false;
|
||||
statusActionDraft.value = '';
|
||||
statusDraft.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
async function applyStatusAction() {
|
||||
if (!currentOrder.value || !statusActionDraft.value) {
|
||||
async function applyStatusChange() {
|
||||
if (!currentOrder.value || !statusDraft.value) {
|
||||
closeStatusEditor();
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusDraft.value === currentOrder.value.status) {
|
||||
closeStatusEditor();
|
||||
return;
|
||||
}
|
||||
@@ -315,25 +274,10 @@ async function applyStatusAction() {
|
||||
statusMutationPending.value = true;
|
||||
|
||||
try {
|
||||
if (statusActionDraft.value === 'APPROVE') {
|
||||
await finalizeOrderMutation.mutate({
|
||||
orderId: currentOrder.value.id,
|
||||
decision: Decision.Approve,
|
||||
});
|
||||
}
|
||||
else if (statusActionDraft.value === 'REJECT') {
|
||||
await finalizeOrderMutation.mutate({
|
||||
orderId: currentOrder.value.id,
|
||||
decision: Decision.Reject,
|
||||
});
|
||||
}
|
||||
else if (statusActionDraft.value === 'START') {
|
||||
await startWorkMutation.mutate({ orderId: currentOrder.value.id });
|
||||
}
|
||||
else if (statusActionDraft.value === 'COMPLETE') {
|
||||
await completeOrderMutation.mutate({ orderId: currentOrder.value.id });
|
||||
}
|
||||
|
||||
await setOrderStatusMutation.mutate({
|
||||
orderId: currentOrder.value.id,
|
||||
status: statusDraft.value,
|
||||
});
|
||||
await refetchOrder();
|
||||
}
|
||||
finally {
|
||||
@@ -343,14 +287,14 @@ async function applyStatusAction() {
|
||||
}
|
||||
|
||||
watch(
|
||||
[offerReady, offerSignature, publishedSignature],
|
||||
([ready, nextSignature, currentSignature]) => {
|
||||
[offerSignature, publishedSignature],
|
||||
([nextSignature, currentSignature]) => {
|
||||
if (autosaveTimer) {
|
||||
clearTimeout(autosaveTimer);
|
||||
autosaveTimer = null;
|
||||
}
|
||||
|
||||
if (!ready || !canEditOffer.value || !nextSignature || nextSignature === currentSignature || autosavePending.value) {
|
||||
if (!canEditOffer.value || !nextSignature || nextSignature === currentSignature || autosavePending.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -381,55 +325,35 @@ watch(
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="surface-card rounded-3xl p-5">
|
||||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||||
<div class="space-y-2">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#6a8a76]">Статус заказа</p>
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#6a8a76]">Статус заказа</p>
|
||||
|
||||
<label v-if="editingStatus && canEditStatus" class="block">
|
||||
<select
|
||||
v-model="statusActionDraft"
|
||||
data-manager-status-select
|
||||
class="w-full min-w-[220px] rounded-2xl bg-[#f3f5f4] px-4 py-3 text-sm font-semibold text-[#123824] outline-none transition focus:shadow-[0_0_0_3px_rgba(19,153,87,0.12)]"
|
||||
:disabled="statusMutationPending"
|
||||
@change="void applyStatusAction()"
|
||||
@blur="closeStatusEditor"
|
||||
>
|
||||
<option value="" disabled>Выберите статус</option>
|
||||
<option
|
||||
v-for="option in statusActions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="rounded-2xl px-0 py-0 text-left"
|
||||
:class="canEditStatus ? 'cursor-pointer' : 'cursor-default'"
|
||||
@dblclick="void openStatusEditor()"
|
||||
<label v-if="editingStatus" class="mt-3 block">
|
||||
<select
|
||||
v-model="statusDraft"
|
||||
data-manager-status-select
|
||||
class="w-full min-w-[220px] rounded-2xl bg-[#f3f5f4] px-4 py-3 text-sm font-semibold text-[#123824] outline-none transition focus:shadow-[0_0_0_3px_rgba(19,153,87,0.12)]"
|
||||
:disabled="statusMutationPending"
|
||||
@change="void applyStatusChange()"
|
||||
@blur="closeStatusEditor"
|
||||
>
|
||||
<option
|
||||
v-for="option in statusOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
<OrdersOrderStatusBadge :status="currentOrder.status" />
|
||||
</button>
|
||||
</div>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<p class="text-sm text-[#5c7b69]">
|
||||
{{
|
||||
statusMutationPending
|
||||
? 'Обновляем статус...'
|
||||
: canEditStatus
|
||||
? 'Двойной клик по статусу, чтобы изменить.'
|
||||
: 'Статус уже финальный.'
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="mt-4 max-w-2xl text-sm leading-6 text-[#355947]">
|
||||
{{ managerStatusSummary }}
|
||||
</p>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="mt-3 rounded-2xl px-0 py-0 text-left"
|
||||
@dblclick="void openStatusEditor()"
|
||||
>
|
||||
<OrdersOrderStatusBadge :status="currentOrder.status" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -515,16 +439,14 @@ watch(
|
||||
<p class="text-sm text-[#5c7b69]">
|
||||
{{
|
||||
offerTotal == null
|
||||
? 'Итог по заказу появится после заполнения всех цен.'
|
||||
? currentOrder.totalPrice == null
|
||||
? 'Итог пока не задан.'
|
||||
: `Текущий итог: ${formatPrice(currentOrder.totalPrice)}`
|
||||
: autosavePending
|
||||
? `Сохраняем: ${formatPrice(offerTotal)}`
|
||||
: `Текущий итог: ${formatPrice(offerTotal)}`
|
||||
}}
|
||||
</p>
|
||||
|
||||
<p v-if="canEditOffer" class="text-xs font-semibold uppercase tracking-[0.14em] text-[#6a8a76]">
|
||||
Двойной клик по цене или условиям, чтобы изменить.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
mutation BlockOrder($input: BlockOrderInput!) {
|
||||
blockOrder(input: $input) {
|
||||
id
|
||||
status
|
||||
blockReason
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
mutation CompleteOrder($orderId: ID!) {
|
||||
completeOrder(orderId: $orderId) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
mutation ManagerFinalizeOrder($orderId: ID!, $decision: Decision!) {
|
||||
managerFinalizeOrder(orderId: $orderId, decision: $decision) {
|
||||
id
|
||||
status
|
||||
managerApproved
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
mutation ManagerSetOrderStatus($orderId: ID!, $status: OrderStatus!) {
|
||||
managerSetOrderStatus(orderId: $orderId, status: $status) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
mutation StartOrderWork($orderId: ID!) {
|
||||
startOrderWork(orderId: $orderId) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -467,17 +467,12 @@ input SetOrderOfferInput {
|
||||
orderId: ID!
|
||||
itemPrices: [OrderItemPriceInput!]!
|
||||
deliveryTerms: String!
|
||||
deliveryFee: Float!
|
||||
deliveryFee: Float
|
||||
}
|
||||
|
||||
input OrderItemPriceInput {
|
||||
itemId: ID!
|
||||
unitPrice: Float!
|
||||
}
|
||||
|
||||
input BlockOrderInput {
|
||||
orderId: ID!
|
||||
reason: String!
|
||||
unitPrice: Float
|
||||
}
|
||||
|
||||
input CreateReferralInput {
|
||||
@@ -526,11 +521,8 @@ type Mutation {
|
||||
submitReadyOrder(input: SubmitReadyOrderInput!): Order!
|
||||
submitCalculationOrder(input: SubmitCalculationOrderInput!): Order!
|
||||
managerSetOrderOffer(input: SetOrderOfferInput!): Order!
|
||||
managerSetOrderStatus(orderId: ID!, status: OrderStatus!): Order!
|
||||
clientReviewOrder(orderId: ID!, decision: Decision!): Order!
|
||||
managerFinalizeOrder(orderId: ID!, decision: Decision!): Order!
|
||||
blockOrder(input: BlockOrderInput!): Order!
|
||||
startOrderWork(orderId: ID!): Order!
|
||||
completeOrder(orderId: ID!): Order!
|
||||
|
||||
createReferral(input: CreateReferralInput!): ReferralLink!
|
||||
addBonusTransaction(input: AddBonusTransactionInput!): BonusTransaction!
|
||||
|
||||
Reference in New Issue
Block a user