Skip to content

Commit

Permalink
chore: some cleanup and organization
Browse files Browse the repository at this point in the history
- remove commented out code from BaseSelect
- pull out cart helpers into their own cart.ts file
  • Loading branch information
mds1 committed Aug 18, 2021
1 parent bc0b2c6 commit f068861
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 91 deletions.
1 change: 0 additions & 1 deletion app/src/components/BaseSelect.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<template>
<Listbox as="div" :modelValue="modelValue" @update:model-value="$emit('update:modelValue', $event)">
<!-- <ListboxLabel class="block text-sm font-medium text-gray-700"> {{ description }} </ListboxLabel> -->
<div class="mt-1 relative">
<ListboxButton
class="
Expand Down
89 changes: 89 additions & 0 deletions app/src/utils/cart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { BigNumber, BigNumberish } from 'src/utils/ethers';
import { Donation, Grant, SwapSummary } from '@dgrants/types';
import { CartItem, CartItemOptions } from 'src/types';
import { SUPPORTED_TOKENS_MAPPING } from 'src/utils/constants';

const CART_KEY = 'cart';
const DEFAULT_CONTRIBUTION_TOKEN_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; // DAI
const DEFAULT_CONTRIBUTION_AMOUNT = 5; // this is converted to a parsed BigNumber at checkout

// --- Modifying cart ---
export function loadCart(): CartItemOptions[] {
try {
// Return empty array if nothing found
const rawCart = localStorage.getItem(CART_KEY);
if (!rawCart) return [];

// Parse the data. If the data is an array, return it,
const cart = JSON.parse(rawCart);
if (Array.isArray(cart)) return cart;

// Otherwise clear the localStorage key and return empty array
localStorage.removeItem(CART_KEY);
return [];
} catch (e) {
console.warn('Could not read any existing cart data from localStorage. Defaulting to empty cart');
return [];
}
}

// Adds a grant to the cart
export function addToCart(grant: Grant | null | undefined): CartItemOptions[] {
if (!grant) return []; // null and undefined input types are to avoid lint errors when calling this from a template
// If this grant is already in the cart, do nothing
const cart = loadCart();
if (cart.map((grant) => grant.grantId).includes(grant.id.toString())) return cart;

// Otherwise, add it to the cart and update localStorage
cart.push({
grantId: grant.id.toString(),
contributionTokenAddress: DEFAULT_CONTRIBUTION_TOKEN_ADDRESS,
contributionAmount: DEFAULT_CONTRIBUTION_AMOUNT,
});
localStorage.setItem(CART_KEY, JSON.stringify(cart));
return cart;
}

// Removes a grant from the cart
export function removeFromCart(grantId: BigNumberish): CartItemOptions[] {
const cart = loadCart();
const newCart = cart.filter((grant) => grant.grantId !== BigNumber.from(grantId).toString());
localStorage.setItem(CART_KEY, JSON.stringify(newCart));
return newCart;
}

// Clears the cart
export function clearCart(): CartItemOptions[] {
localStorage.removeItem(CART_KEY);
return [];
}

// Sets the full cart
export function setCart(cart: CartItemOptions[]) {
localStorage.setItem(CART_KEY, JSON.stringify(cart));
}

// --- Parsing cart data ---
// Convert a cart into an array of objects summarizing the cart info, with human-readable values
export function getCartSummary(cart: CartItem[]): Record<keyof typeof SUPPORTED_TOKENS_MAPPING, number> {
const output: Record<keyof typeof SUPPORTED_TOKENS_MAPPING, number> = {};
for (const item of cart) {
const tokenAddress = item.contributionToken.address;
if (tokenAddress in output) output[tokenAddress] += item.contributionAmount;
else output[tokenAddress] = item.contributionAmount;
}
return output;
}

// Takes an array of cart items and returns inputs needed for the GrantRoundManager.donate() method
export function formatDonateInputs(cart: CartItem[]): { swaps: SwapSummary[]; donations: Donation[] } {
const swaps: SwapSummary[] = [];
const donations: Donation[] = [];

for (const item of cart) {
// TODO use helper methods from @dgrants/utils
item;
}

return { swaps, donations };
}
92 changes: 5 additions & 87 deletions app/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
import router from 'src/router/index';
import { RouteLocationRaw } from 'vue-router';
import { BigNumber, BigNumberish, Contract, ContractTransaction, isAddress } from 'src/utils/ethers';
import { SUPPORTED_TOKENS_MAPPING } from 'src/utils/constants';
import { CartItem, CartItemOptions } from 'src/types';
import { Donation, Grant, GrantRound, SwapSummary } from '@dgrants/types';
import { GrantRound } from '@dgrants/types';

// --- Formatters ---
// Returns an address with the following format: 0x1234...abcd
Expand Down Expand Up @@ -42,68 +40,6 @@ export function isValidAddress(val: string | undefined) {
return val && isAddress(val);
}

// --- Grants + Cart ---
const CART_KEY = 'cart';
const DEFAULT_CONTRIBUTION_TOKEN_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; // DAI
const DEFAULT_CONTRIBUTION_AMOUNT = 5; // this is converted to a parsed BigNumber at checkout

// Loads cart data
export function loadCart(): CartItemOptions[] {
// Return empty array if nothing found
const rawCart = localStorage.getItem(CART_KEY);
if (!rawCart) return [];

// Parse the data. If the data is an array, return it,
const cart = JSON.parse(rawCart);
if (Array.isArray(cart)) return cart;

// Otherwise clear the localStorage key and return empty array
localStorage.removeItem(CART_KEY);
return [];
}

// Adds a grant to the cart
export function addToCart(grant: Grant | null | undefined): CartItemOptions[] {
if (!grant) return []; // null and undefined input types are to avoid lint errors when calling this from a template
// If this grant is already in the cart, do nothing
const cart = loadCart();
if (cart.map((grant) => grant.grantId).includes(grant.id.toString())) return cart;

// Otherwise, add it to the cart and update localStorage
cart.push({
grantId: grant.id.toString(),
contributionTokenAddress: DEFAULT_CONTRIBUTION_TOKEN_ADDRESS,
contributionAmount: DEFAULT_CONTRIBUTION_AMOUNT,
});
localStorage.setItem(CART_KEY, JSON.stringify(cart));
return cart;
}

// Removes a grant from the cart
export function removeFromCart(grantId: BigNumberish): CartItemOptions[] {
const cart = loadCart();
const newCart = cart.filter((grant) => grant.grantId !== BigNumber.from(grantId).toString());
localStorage.setItem(CART_KEY, JSON.stringify(newCart));
return newCart;
}

// Clears the cart
export function clearCart(): CartItemOptions[] {
localStorage.removeItem(CART_KEY);
return [];
}

// Sets the full cart
export function setCart(cart: CartItemOptions[]) {
localStorage.setItem(CART_KEY, JSON.stringify(cart));
}

// Check against the grantRounds status for a match
export function hasStatus(status: string) {
// returns a fn (currying the given status)
return (round: GrantRound) => round.status === status;
}

// --- Tokens ---
// Check for approved allowance
export async function checkAllowance(token: Contract, ownerAddress: string | undefined, spenderAddress: string) {
Expand All @@ -120,28 +56,10 @@ export async function getApproval(token: Contract, address: string, amount: BigN
}

// --- Other ---
// Convert a cart into an array of objects summarizing the cart info, with human-readable values
export function getCartSummary(cart: CartItem[]): Record<keyof typeof SUPPORTED_TOKENS_MAPPING, number> {
const output: Record<keyof typeof SUPPORTED_TOKENS_MAPPING, number> = {};
for (const item of cart) {
const tokenAddress = item.contributionToken.address;
if (tokenAddress in output) output[tokenAddress] += item.contributionAmount;
else output[tokenAddress] = item.contributionAmount;
}
return output;
}

// Takes an array of cart items and returns inputs needed for the GrantRoundManager.donate() method
export function formatDonateInputs(cart: CartItem[]): { swaps: SwapSummary[]; donations: Donation[] } {
const swaps: SwapSummary[] = [];
const donations: Donation[] = [];

for (const item of cart) {
// TODO use helper methods from @dgrants/utils
item;
}

return { swaps, donations };
// Check against the grantRounds status for a match
export function hasStatus(status: string) {
// returns a fn (currying the given status)
return (round: GrantRound) => round.status === status;
}

// Navigates to the specified page and pushes a new entry into the history stack
Expand Down
3 changes: 2 additions & 1 deletion app/src/views/Cart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ import { SUPPORTED_TOKENS, SUPPORTED_TOKENS_MAPPING } from 'src/utils/constants'
import { BigNumberish } from 'src/utils/ethers';
import useDataStore from 'src/store/data';
import { CartItem, CartItemOptions } from 'src/types';
import { pushRoute, clearCart, loadCart, removeFromCart, setCart, formatDonateInputs, getCartSummary, } from 'src/utils/utils'; // prettier-ignore
import { clearCart, loadCart, removeFromCart, setCart, formatDonateInputs, getCartSummary } from 'src/utils/cart';
import { pushRoute } from 'src/utils/utils';
function useCart() {
const { grants } = useDataStore();
Expand Down
3 changes: 2 additions & 1 deletion app/src/views/GrantRegistryGrantDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ import useWalletStore from 'src/store/wallet';
// --- Methods and Data ---
import { GRANT_REGISTRY_ADDRESS, GRANT_REGISTRY_ABI } from 'src/utils/constants';
import { Contract, ContractTransaction } from 'src/utils/ethers';
import { addToCart, isValidAddress, isValidUrl } from 'src/utils/utils';
import { addToCart } from 'src/utils/cart';
import { isValidAddress, isValidUrl } from 'src/utils/utils';
// --- Types ---
import { GrantRegistry } from '@dgrants/contracts';
Expand Down
3 changes: 2 additions & 1 deletion app/src/views/GrantRegistryList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@

<script lang="ts">
import { defineComponent } from 'vue';
import { addToCart, formatAddress, pushRoute } from 'src/utils/utils';
import { addToCart } from 'src/utils/cart';
import { formatAddress, pushRoute } from 'src/utils/utils';
import useDataStore from 'src/store/data';
export default defineComponent({
Expand Down

0 comments on commit f068861

Please sign in to comment.