Skip to content

Commit

Permalink
feat(txn_presets): add ability to "favorite" a preset
Browse files Browse the repository at this point in the history
Closes #168
  • Loading branch information
No-Cash-7970 committed Oct 23, 2024
1 parent db2614d commit 572ed21
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 2 deletions.
42 changes: 41 additions & 1 deletion src/app/[lang]/txn/TxnPreset.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import Link from "next/link";
import { useAtom } from "jotai";
import { TFunction } from "i18next";
import { IconStar, IconStarFilled } from "@tabler/icons-react";
import { txnPresetFavsAtom } from "@/app/lib/app-settings";

type Props = {
/** Text and other elements to be used as the description */
Expand All @@ -13,6 +17,12 @@ type Props = {
actionDisabled?: boolean,
/** Color name used for decoration */
color?: 'primary'|'secondary'|'accent'|'neutral',
/** Unique identifier for the preset. Used when adding and removing preset from list of
* favorites
*/
presetName: string,
/** I18next "t" function */
t: TFunction,
};

/** Small section containing a heading, description, and a link for a transaction preset */
Expand All @@ -23,9 +33,12 @@ export default function TxnPreset({
actionURL,
actionDisabled = false,
color = 'primary',
presetName,
t,
}: Props) {
const [txnPresetFavs, setTxnPresetFavs] = useAtom(txnPresetFavsAtom);
return (
<div className={'card card-compact shadow-md border border-opacity-50'
<div className={'card shadow-md border border-opacity-50'
+ (color === 'primary' ? ' border-primary' : '')
+ (color === 'secondary' ? ' border-secondary' : '')
+ (color === 'accent' ? ' border-accent' : '')
Expand Down Expand Up @@ -56,6 +69,33 @@ export default function TxnPreset({
</Link>
</div>
</div>
{txnPresetFavs.indexOf(presetName) === -1 // If preset is not in favorites
? (
<button type="button" className="btn btn-sm btn-ghost absolute top-1 end-1 px-1"
title={t('favorites.add', {presetName: heading})}
onClick={() => setTxnPresetFavs([...txnPresetFavs, presetName])}
>
<IconStar size={22} className="opacity-50" />
</button>
)
: (
<button type="button" className="btn btn-sm btn-ghost absolute top-1 end-1 px-1"
title={t('favorites.remove', {presetName: heading})}
onClick={() => {
const newFavs = [...txnPresetFavs];
newFavs.splice(newFavs.indexOf(presetName), 1); // Remove preset from favorites
setTxnPresetFavs(newFavs);
}}
>
<IconStarFilled size={22} className={
(color === 'primary' ? 'text-primary' : '')
+ (color === 'secondary' ? 'text-secondary' : '')
+ (color === 'accent' ? 'text-accent' : '')
+ (color === 'neutral' ? 'text-neutral' : '')
} />
</button>
)
}
</div>
);
}
61 changes: 60 additions & 1 deletion src/app/[lang]/txn/TxnPresetsList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ jest.mock('next/navigation', () => ({
import TxnPresetsList from './TxnPresetsList';

describe('Transaction Presets List', () => {
beforeEach(() => {
localStorage.clear();
});

it('only shows favorite items when "favorites" category is selected', async () => {
localStorage.setItem('txnPresetFavs', '["transfer","reg_offline","asset_transfer"]');
render(<TxnPresetsList />);

await userEvent.selectOptions(screen.getByRole('combobox'), 'favorites'); // Select 'favorites'

expect(screen.getByRole('heading', {level: 2})).toHaveTextContent('favorites.heading');
expect(screen.getByText('transfer_algos.description')).toBeInTheDocument();
expect(screen.getByText('reg_offline.description')).toBeInTheDocument();
expect(screen.getByText('asset_transfer.description')).toBeInTheDocument();
});

it('only shows general items when "general" category is selected', async () => {
render(<TxnPresetsList />);
Expand Down Expand Up @@ -77,7 +92,7 @@ describe('Transaction Presets List', () => {

await userEvent.selectOptions(screen.getByRole('combobox'), 'all'); // Select 'all'

expect(screen.getAllByRole('heading', {level: 2})).toHaveLength(4); // Have all 4 headings
expect(screen.getAllByRole('heading', {level: 2})).toHaveLength(5); // Have all 4 headings

expect(screen.getByText('transfer_algos.description')).toBeInTheDocument();
expect(screen.getByText('rekey_account.description')).toBeInTheDocument();
Expand Down Expand Up @@ -106,4 +121,48 @@ describe('Transaction Presets List', () => {
expect(screen.getByText('reg_nonpart.description')).toBeInTheDocument();
});

it('adds preset to "favorites" when "add favorite" button for preset is clicked', async () => {
render(<TxnPresetsList />);

expect(screen.getByText('favorites.none')).toBeInTheDocument();

const favBtn = screen.getAllByTitle('favorites.add')[0];
await userEvent.click(favBtn);

const storedFavs = localStorage.getItem('txnPresetFavs') ?? '';
expect(storedFavs).toBe('["transfer"]');
expect(screen.getAllByTitle('favorites.remove'))
.toHaveLength(2);
});

// eslint-disable-next-line max-len
it('removes preset from "favorites" category when "remove favorite" button of the copy in the "favorites" category is clicked',
async () => {
localStorage.setItem('txnPresetFavs', '["transfer"]');
render(<TxnPresetsList />);

// Get the favorites button for the copy of the preset listed under "Favorites"
const favBtn = screen.getAllByTitle('favorites.remove')[0];
await userEvent.click(favBtn);

const storedFavs = localStorage.getItem('txnPresetFavs') ?? '';
expect(storedFavs).toBe('[]');
expect(screen.getByText('favorites.none')).toBeInTheDocument();
});

// eslint-disable-next-line max-len
it('removes preset from "favorites" category when "remove favorite" button of the copy NOT in the "favorites" category is clicked',
async () => {
localStorage.setItem('txnPresetFavs', '["transfer"]');
render(<TxnPresetsList />);

// Get the favorites button for the preset listed under its normal category
const favBtn = screen.getAllByTitle('favorites.remove')[1];
await userEvent.click(favBtn);

const storedFavs = localStorage.getItem('txnPresetFavs') ?? '';
expect(storedFavs).toBe('[]');
expect(screen.getByText('favorites.none')).toBeInTheDocument();
});

});
Loading

0 comments on commit 572ed21

Please sign in to comment.