Skip to content

Commit

Permalink
feat: setup list of items in cart on cart page
Browse files Browse the repository at this point in the history
  • Loading branch information
mds1 committed Aug 18, 2021
1 parent 3bdc878 commit 279e1d4
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 13 deletions.
16 changes: 12 additions & 4 deletions app/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ export function loadCart(): CartItemOptions[] {
}

// Adds a grant to the cart
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
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;
if (cart.map((grant) => grant.grantId).includes(grant.id.toString())) return cart;

// Otherwise, add it to the cart and update localStorage
cart.push({
Expand All @@ -76,13 +76,21 @@ export function addToCart(grant: Grant | null | undefined) {
contributionAmount: DEFAULT_CONTRIBUTION_AMOUNT,
});
localStorage.setItem(CART_KEY, JSON.stringify(cart));
return cart;
}

// Removes a grant from the cart
export function removeFromCart(grantId: BigNumberish) {
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 [];
}

// Check against the grantRounds status for a match
Expand Down
65 changes: 56 additions & 9 deletions app/src/views/Cart.vue
Original file line number Diff line number Diff line change
@@ -1,45 +1,92 @@
<template>
<h1 class="my-6 text-center text-3xl font-extrabold text-gray-900">Cart</h1>
<!-- Header -->
<h1 class="my-6 text-center text-3xl font-extrabold text-gray-900">Cart {{ cart.length }}</h1>

<!-- Empty cart -->
<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>

<!-- Cart has items -->
<div v-else>
<div v-for="item in cart" :key="item.grantId" class="mb-10">
<div>{{ item }}</div>
<!-- Cart toolbar -->
<div class="flex justify-between mb-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2 border-t-2 border-b-2">
<div class="flex justify-start">
<button class="btn btn-flat mr-5">Save as collection</button>
<button class="btn btn-flat">Share cart</button>
</div>
<button @click="clearCartState" class="btn btn-flat">Clear cart</button>
</div>
<!-- Cart items -->
<div class="bg-white shadow overflow-hidden sm:rounded-md max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2">
<ul class="divide-y divide-gray-200">
<!-- For each grant -->
<li v-for="grant in cart" :key="grant.grantId">
<div class="flex justify-between items-center px-4 py-4 sm:px-6">
<!-- Logo and name -->
<div class="flex items-center">
<img class="h-12 w-12" :src="grant.logoUrl || 'src/assets/logo.png'" alt="" />
<p class="text-sm text-left font-medium truncate">
{{ grant.name || 'name not found' }}
</p>
</div>

<!-- Contribution info -->
<div class="flex space-x-2">
<!-- Contribution token and amount -->
<div class="flex-none flex">
<BaseInput />
</div>

<!-- Match estimate -->
<div class="flex-none hidden md:block">
<p class="text-sm text-left text-gray-400">not in an active round</p>
</div>

<!-- Delete from cart -->
<div>
<XIcon class="flex-none h-5 w-5 text-gray-400" aria-hidden="true" />
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue';
import { pushRoute, loadCart } from 'src/utils/utils';
import { computed, defineComponent, ref } from 'vue';
import { pushRoute, clearCart, loadCart } from 'src/utils/utils';
import useDataStore from 'src/store/data';
import { CartItemOptions } from 'src/types';
import { Grant } from '@dgrants/types';
import { XIcon } from '@heroicons/vue/solid';
import BaseInput from 'src/components/BaseInput.vue';
type CartItem = CartItemOptions & Grant;
function useCart() {
const { grants } = useDataStore();
const rawCart = ref<CartItemOptions[]>(loadCart());
const clearCartState = () => (rawCart.value = clearCart());
const cart = computed(() => {
// Load cart info form localStorage, then concatenate it with grant data from store
const rawCart = loadCart();
return rawCart.map((cartItem) => {
// Use cart info form localStorage and concatenate it with grant data from store
return rawCart.value.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 };
return { cart, clearCartState };
}
export default defineComponent({
name: 'Cart',
components: { BaseInput, XIcon },
setup() {
return { ...useCart(), pushRoute };
},
Expand Down

0 comments on commit 279e1d4

Please sign in to comment.