Skip to content
This repository has been archived by the owner on Nov 2, 2024. It is now read-only.

🐛 Fix bug where quantity does not include chest items #1230

Merged
merged 2 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions backend/services/core/graphql.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -13670,6 +13670,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "productId",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "UUID",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "variant",
"description": null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable('user_inventory_item', (table) => {
table.uuid('product_id').nullable().references('product.id').onDelete('CASCADE');
});
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable('user_inventory_item', (table) => {
table.dropColumn('product_id');
});
}
3 changes: 2 additions & 1 deletion backend/services/core/src/datasources/WebshopAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default class WebshopAPI extends dbUtils.KnexDataSource {

getProducts(ctx: context.UserContext, categoryId?: string): Promise<gql.Product[]> {
return this.withAccess('webshop:read', ctx, async () => {
let query = this.knex<sql.Product>(TABLE.PRODUCT);
let query = this.knex<sql.Product>(TABLE.PRODUCT).whereNull('deleted_at');
if (categoryId) {
query = query.where({ category_id: categoryId }); // not tested
}
Expand Down Expand Up @@ -665,6 +665,7 @@ export default class WebshopAPI extends dbUtils.KnexDataSource {
variant: productInventory.variant,
user_inventory_id: userInventory.id,
product_inventory_id: orderItem.product_inventory_id,
product_id: product.id,
category_id: product.category_id,
}));
}
Expand Down
1 change: 1 addition & 0 deletions backend/services/core/src/schemas/webshop.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type UserInventory {

type UserInventoryItem {
id: UUID!
productId: UUID
name: String!
description: String!
paidPrice: Float!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,5 @@ export const convertUserInventoryItem = (
paidAt: item.paid_at,
paidPrice: item.paid_price,
consumedAt: item.consumed_at,
productId: item.product_id,
});
2 changes: 2 additions & 0 deletions backend/services/core/src/types/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1770,6 +1770,7 @@ export type UserInventoryItem = {
name: Scalars['String']['output'];
paidAt: Scalars['Date']['output'];
paidPrice: Scalars['Float']['output'];
productId?: Maybe<Scalars['UUID']['output']>;
variant?: Maybe<Scalars['String']['output']>;
};

Expand Down Expand Up @@ -3057,6 +3058,7 @@ export type UserInventoryItemResolvers<ContextType = any, ParentType extends Res
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
paidAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
paidPrice?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
productId?: Resolver<Maybe<ResolversTypes['UUID']>, ParentType, ContextType>;
variant?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
Expand Down
1 change: 1 addition & 0 deletions backend/services/core/src/types/webshop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export interface UserInventoryItem {
id: UUID,
user_inventory_id: UUID,
product_inventory_id: UUID,
product_id: UUID,
category_id: UUID,
student_id: UUID,
name: string,
Expand Down
1 change: 1 addition & 0 deletions frontend/api/chest.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ query MyChest($studentId: String!) {
}
paidAt
consumedAt
productId
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions frontend/components/Nolla/locales/en.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export default {
map: 'Map',
},
index: {
bite: {
copy: 'Beställ mat med gratis leverans i en månad med koden',
},
hero: {
title: (
<>
Expand Down
3 changes: 3 additions & 0 deletions frontend/components/Nolla/locales/sv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export default {
map: 'Karta',
},
index: {
bite: {
copy: 'Beställ mat med gratis leverans i en månad med koden',
},
hero: {
title: (
<>
Expand Down
24 changes: 17 additions & 7 deletions frontend/components/Webshop/Product.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,24 @@
import Link from 'next/link';
import {
MyCartQuery,
ProductsQuery, useAddToMyCartMutation, useMyCartQuery, useProductsQuery,
MyChestQuery,
ProductsQuery, useAddToMyCartMutation, useMyCartQuery, useMyChestQuery, useProductsQuery,
} from '~/generated/graphql';
import handleApolloError from '~/functions/handleApolloError';
import { useSnackbar } from '~/providers/SnackbarProvider';
import { useApiAccess } from '~/providers/ApiAccessProvider';
import { useUser } from '~/providers/UserProvider';

function getQuantityInMyCart(productId: string, myCart?: MyCartQuery['myCart']) {
if (!myCart) return 0;
function getQuantityInMyCart(productId: string, myCart?: MyCartQuery['myCart'], myChest?: MyChestQuery['chest']) {
const cartItem = myCart?.cartItems.find((p) => p.id === productId);
if (!cartItem) return 0;
const quantities = cartItem.inventory.map((i) => i.quantity);
return quantities.reduce((a, b) => a + b, 0);
const chestItems = myChest?.items.filter((p) => p.productId === productId);
let quantity = 0;
if (cartItem) {
const quantities = cartItem.inventory.map((i) => i.quantity);
quantity += quantities.reduce((a, b) => a + b, 0);
}
quantity += chestItems.length;
return quantity;
}

// time diff in milliseconds
Expand All @@ -54,11 +60,15 @@

export default function Product({ product }: { product: ProductsQuery['products'][number] }) {
const { t } = useTranslation();
const { user } = useUser();
const { showMessage } = useSnackbar();
const [selectedVariant, setSelectedVariant] = useState(product.inventory[0]);
const [timeLeft, setTimeLeft] = useState(Number.MAX_VALUE);
const { refetch: refetchMyCart, data } = useMyCartQuery();
const quantityInMyCart = getQuantityInMyCart(product.id, data?.myCart);
const { data: chestData } = useMyChestQuery({
variables: { studentId: user?.student_id },
});
const quantityInMyCart = getQuantityInMyCart(product.id, data?.myCart, chestData?.chest);
const { refetch: refetchProducts } = useProductsQuery(
{ variables: { categoryId: product.category.id } },
);
Expand Down Expand Up @@ -88,7 +98,7 @@
setTimeLeft(0);
}
return () => clearInterval(interval);
}, [product]);

Check warning on line 101 in frontend/components/Webshop/Product.tsx

View workflow job for this annotation

GitHub Actions / linter_check

React Hook useEffect has a missing dependency: 'selectedVariant'. Either include it or remove the dependency array

const { hasAccess } = useApiAccess();

Expand Down
4 changes: 3 additions & 1 deletion frontend/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,7 @@ export type UserInventoryItem = {
name: Scalars['String'];
paidAt: Scalars['Date'];
paidPrice: Scalars['Float'];
productId?: Maybe<Scalars['UUID']>;
variant?: Maybe<Scalars['String']>;
};

Expand Down Expand Up @@ -2068,7 +2069,7 @@ export type MyChestQueryVariables = Exact<{
}>;


export type MyChestQuery = { __typename?: 'Query', chest?: { __typename?: 'UserInventory', id: any, items: Array<{ __typename?: 'UserInventoryItem', id: any, name: string, description: string, paidPrice: number, imageUrl: string, variant?: string | null, paidAt: any, consumedAt?: any | null, category?: { __typename?: 'ProductCategory', id: any, name: string, description: string } | null } | null> } | null };
export type MyChestQuery = { __typename?: 'Query', chest?: { __typename?: 'UserInventory', id: any, items: Array<{ __typename?: 'UserInventoryItem', id: any, name: string, description: string, paidPrice: number, imageUrl: string, variant?: string | null, paidAt: any, consumedAt?: any | null, productId?: any | null, category?: { __typename?: 'ProductCategory', id: any, name: string, description: string } | null } | null> } | null };

export type ConsumeItemMutationVariables = Exact<{
itemId: Scalars['UUID'];
Expand Down Expand Up @@ -4095,6 +4096,7 @@ export const MyChestDocument = gql`
}
paidAt
consumedAt
productId
}
}
}
Expand Down
Loading
Loading