Skip to content

Commit

Permalink
feat: setup cart page
Browse files Browse the repository at this point in the history
  • Loading branch information
mds1 committed Aug 18, 2021
1 parent 4f463b2 commit 3bdc878
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 8 deletions.
2 changes: 1 addition & 1 deletion app/src/components/LayoutHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import { ExclamationIcon } from '@heroicons/vue/solid';
const navigation = [
{ name: 'Home', href: '/' },
{ name: 'About', href: '/about' },
{ name: 'Docs', href: '/docs' },
{ name: 'Cart', href: '/cart' },
{ name: 'Contact', href: '/contact' },
];
Expand Down
1 change: 1 addition & 0 deletions app/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Home from '../views/Home.vue';
const routes: Array<RouteRecordRaw> = [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: () => import('../views/About.vue') },
{ path: '/cart', name: 'Cart', component: () => import('../views/Cart.vue') },
{ path: '/dgrants', name: 'dgrants', component: () => import('../views/GrantRegistryList.vue') },
{ path: '/dgrants/new', name: 'dgrants-new', component: () => import('../views/GrantRegistryNewGrant.vue') },
{ path: '/dgrants/:id', name: 'dgrants-id', component: () => import('../views/GrantRegistryGrantDetail.vue') },
Expand Down
5 changes: 5 additions & 0 deletions app/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
// App-specific type definition go here
export type CartItemOptions = {
grantId: string;
contributionTokenAddress: string; // store address instead of TokenInfo to reduce localStorage size used
contributionAmount: string;
};
11 changes: 4 additions & 7 deletions app/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import router from 'src/router/index';
import { RouteLocationRaw } from 'vue-router';
import { BigNumber, isAddress, parseUnits } from 'src/utils/ethers';
import { CartItemOptions } from 'src/types';
import { BigNumberish, Contract, ContractTransaction } from 'ethers';
import { Grant, GrantRound } from '@dgrants/types';

Expand Down Expand Up @@ -45,14 +46,9 @@ export function isValidAddress(val: string | undefined) {
const CART_KEY = 'cart';
const DEFAULT_CONTRIBUTION_TOKEN_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; // DAI
const DEFAULT_CONTRIBUTION_AMOUNT = parseUnits('5', 18).toString(); // DAI has 18 decimals
type CartItem = {
grantId: string;
contributionTokenAddress: string; // store address instead of TokenInfo to reduce localStorage size used
contributionAmount: string;
};

// Loads cart data
export function loadCart(): CartItem[] {
export function loadCart(): CartItemOptions[] {
// Return empty array if nothing found
const rawCart = localStorage.getItem(CART_KEY);
if (!rawCart) return [];
Expand All @@ -67,7 +63,8 @@ export function loadCart(): CartItem[] {
}

// Adds a grant to the cart
export function addToCart(grant: Grant) {
export function addToCart(grant: Grant | null | undefined) {
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;
Expand Down
47 changes: 47 additions & 0 deletions app/src/views/Cart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<template>
<h1 class="my-6 text-center text-3xl font-extrabold text-gray-900">Cart</h1>

<div v-if="cart.length === 0">
<div>Your cart is empty</div>
<button @click="pushRoute({ name: 'dgrants' })" class="btn btn-primary mt-6">Browse Grants</button>
</div>

<div v-else>
<div v-for="item in cart" :key="item.grantId" class="mb-10">
<div>{{ item }}</div>
</div>
</div>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue';
import { pushRoute, loadCart } from 'src/utils/utils';
import useDataStore from 'src/store/data';
import { CartItemOptions } from 'src/types';
import { Grant } from '@dgrants/types';
type CartItem = CartItemOptions & Grant;
function useCart() {
const { grants } = useDataStore();
const cart = computed(() => {
// Load cart info form localStorage, then concatenate it with grant data from store
const rawCart = loadCart();
return rawCart.map((cartItem) => {
// grants.value is likely undefined as page first loads before data is fetched, hence the `grants.value &&`
const grant = grants.value && grants.value.filter((grant) => grant.id.toString() === cartItem.grantId)[0]; // TODO `grants.value.filter` may be slow for large number of grants
return { ...cartItem, ...grant } as CartItem;
});
});
return { cart, grants };
}
export default defineComponent({
name: 'Cart',
setup() {
return { ...useCart(), pushRoute };
},
});
</script>

0 comments on commit 3bdc878

Please sign in to comment.