Files
bruno/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js
Sanjai Kumar 71413b9154 chore: update delete confirmation modals to use danger button color (#6589)
* refactor: remove size prop from Button components for consistency across modals and improve styling

* style: update confirm button colors in modal components for consistency
2025-12-31 18:13:33 +05:30

179 lines
5.6 KiB
JavaScript

import React, { useEffect, useMemo } from 'react';
import each from 'lodash/each';
import filter from 'lodash/filter';
import groupBy from 'lodash/groupBy';
import { useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import { findCollectionByUid, flattenItems, isItemARequest, hasRequestChanges } from 'utils/collections';
import { pluralizeWord } from 'utils/common';
import { completeQuitFlow } from 'providers/ReduxStore/slices/app';
import { saveMultipleRequests, saveMultipleCollections, saveMultipleFolders } from 'providers/ReduxStore/slices/collections/actions';
import { IconAlertTriangle } from '@tabler/icons';
import Modal from 'components/Modal';
import Button from 'ui/Button';
const SaveRequestsModal = ({ onClose }) => {
const MAX_UNSAVED_ITEMS_TO_SHOW = 5;
const collections = useSelector((state) => state.collections.collections);
const tabs = useSelector((state) => state.tabs.tabs);
const dispatch = useDispatch();
const allDrafts = useMemo(() => {
const requestDrafts = [];
const collectionDrafts = [];
const folderDrafts = [];
const tabsByCollection = groupBy(tabs, (t) => t.collectionUid);
Object.keys(tabsByCollection).forEach((collectionUid) => {
const collection = findCollectionByUid(collections, collectionUid);
if (collection) {
// Check for collection draft
if (collection.draft) {
collectionDrafts.push({
type: 'collection',
name: collection.name,
collectionUid: collectionUid
});
}
// Check for request and folder drafts
const items = flattenItems(collection.items);
// Request drafts
const requests = filter(items, (item) => isItemARequest(item) && hasRequestChanges(item));
each(requests, (draft) => {
requestDrafts.push({
type: 'request',
...draft,
collectionUid: collectionUid
});
});
// Folder drafts
const folders = filter(items, (item) => item.type === 'folder' && item.draft);
each(folders, (folder) => {
folderDrafts.push({
type: 'folder',
name: folder.name,
folderUid: folder.uid,
collectionUid: collectionUid
});
});
}
});
return [...collectionDrafts, ...folderDrafts, ...requestDrafts];
}, [collections, tabs]);
const totalDraftsCount = allDrafts.length;
useEffect(() => {
if (totalDraftsCount === 0) {
return dispatch(completeQuitFlow());
}
}, [totalDraftsCount, dispatch]);
const closeWithoutSave = () => {
dispatch(completeQuitFlow());
onClose();
};
const closeWithSave = async () => {
try {
// Separate drafts by type
const collectionDrafts = allDrafts.filter((d) => d.type === 'collection');
const folderDrafts = allDrafts.filter((d) => d.type === 'folder');
const requestDrafts = allDrafts.filter((d) => d.type === 'request');
// Save all collection drafts
if (collectionDrafts.length > 0) {
await dispatch(saveMultipleCollections(collectionDrafts));
}
// Save all folder drafts
if (folderDrafts.length > 0) {
await dispatch(saveMultipleFolders(folderDrafts));
}
// Save all request drafts
if (requestDrafts.length > 0) {
await dispatch(saveMultipleRequests(requestDrafts));
}
dispatch(completeQuitFlow());
onClose();
} catch (error) {
console.error('Error saving drafts:', error);
}
};
if (totalDraftsCount === 0) {
return null;
}
return (
<Modal
size="md"
title="Unsaved changes"
confirmText="Save and Close"
cancelText="Close without saving"
handleCancel={onClose}
disableEscapeKey={true}
disableCloseOnOutsideClick={true}
closeModalFadeTimeout={150}
hideFooter={true}
>
<div className="flex items-center">
<IconAlertTriangle size={32} strokeWidth={1.5} className="text-yellow-600" />
<h1 className="ml-2 text-lg font-medium">Hold on..</h1>
</div>
<p className="mt-4">
Do you want to save the changes you made to the following{' '}
<span className="font-medium">{totalDraftsCount}</span> {pluralizeWord('item', totalDraftsCount)}?
</p>
<ul className="mt-4">
{allDrafts.slice(0, MAX_UNSAVED_ITEMS_TO_SHOW).map((item, index) => {
const prefix
= item.type === 'collection'
? 'Collection: '
: item.type === 'folder'
? 'Folder: '
: 'Request: ';
return (
<li key={`${item.type}-${item.collectionUid || item.uid}-${index}`} className="mt-1 text-xs">
{prefix}
{item.name || item.filename}
</li>
);
})}
</ul>
{totalDraftsCount > MAX_UNSAVED_ITEMS_TO_SHOW && (
<p className="mt-1 text-xs">
...{totalDraftsCount - MAX_UNSAVED_ITEMS_TO_SHOW} additional{' '}
{pluralizeWord('item', totalDraftsCount - MAX_UNSAVED_ITEMS_TO_SHOW)} not shown
</p>
)}
<div className="flex justify-between mt-6">
<div>
<Button color="danger" onClick={closeWithoutSave}>
Don't Save
</Button>
</div>
<div>
<Button className="mr-2" color="secondary" variant="ghost" onClick={onClose}>
Cancel
</Button>
<Button onClick={closeWithSave}>
{totalDraftsCount > 1 ? 'Save All' : 'Save'}
</Button>
</div>
</div>
</Modal>
);
};
export default SaveRequestsModal;