Skip to content
This repository was archived by the owner on Feb 23, 2022. It is now read-only.
Open
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: 9 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ node_modules
dist
.idea
debug.log
build-storybook.log
*.bundle.*
storybook-static/*
src/Containers/HorizontalScrollList/HorizontalScrollList.tsx
src/Containers/MiddleCanvas/DroppableElement.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this in gitignore??

src/Containers/Modal/Modal.tsx
src/Containers/QuestionMarkHover/QuestionMarkHover.stories.tsx
src/Containers/QuestionMarkHover/QuestionMarkHover.tsx
src/Containers/SelectList/SelectList.tsx
src/Fragments/InputFragment.tsx
src/Inputs/Button/Button.tsx

68 changes: 68 additions & 0 deletions src/Containers/MenuItemCard/MenuItemCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import { Meta, Story } from '@storybook/react';
import { MenuItemCard, MenuItemCardProps, LoyaltyPoints, LimitedTimeBanner, SaleTag} from '../../index';
import { createStoryTitle } from '../../Constants';

export default {
title: createStoryTitle('MenuItemCard'),
component: MenuItemCard,
subcomponents: {LoyaltyPoints, LimitedTimeBanner, SaleTag},
argTypes: { onClick: { action: 'Link to next step' } },
} as Meta;

const Template: Story<MenuItemCardProps> = (args) => <MenuItemCard {...args}> <LoyaltyPoints {...args}/>
<LimitedTimeBanner {...args}/> <SaleTag {...args} /> </MenuItemCard>;

export const MenuItemCardBasic = Template.bind({});
MenuItemCardBasic.args = {
itemImage: 'https://keyassets-p2.timeincuk.net/wp/prod/wp-content/uploads/sites/63/2007/09/Ricotta-cheese-pancakes-with-blackberry-butter.jpg',
itemName: 'Blackberry Pancakes',
itemPrice: 15.99,
itemPriceLimit: 1000,
saleAmount: 5,
loyaltyamount: 20,
loyaltypointlimit: 100,
minsRemaining: 120,
sale: false,
soldOut: false,
widthFitContent: false,
heightFitContent: false,
animated: true,
flat: false,
};

export const MenuItemCardStates = Template.bind({});
MenuItemCardStates.args = {
itemImage: 'https://keyassets-p2.timeincuk.net/wp/prod/wp-content/uploads/sites/63/2007/09/Ricotta-cheese-pancakes-with-blackberry-butter.jpg',
itemName: 'Blackberry Pancakes',
itemPrice: 15.99,
itemPriceLimit: 1000,
saleAmount: 5,
loyaltyamount: 0,
loyaltypointlimit: 100,
minsRemaining: 0,
sale: true,
soldOut: true,
widthFitContent: false,
heightFitContent: true,
animated: false,
flat: false,
};

export const MenuItemCardLongText = Template.bind({});
MenuItemCardLongText.args = {
itemImage: 'https://keyassets-p2.timeincuk.net/wp/prod/wp-content/uploads/sites/63/2007/09/Ricotta-cheese-pancakes-with-blackberry-butter.jpg',
itemName: 'Super crazy long combo special order with extra sides and drinks blackberry pancakes',
itemPrice: 2560,
itemPriceLimit: 1000,
saleAmount: 200,
loyaltyamount: 150,
loyaltypointlimit: 100,
minsRemaining: 24000,
sale: false,
soldOut: false,
widthFitContent: false,
heightFitContent: true,
animated: true,
flat: false,
};
189 changes: 189 additions & 0 deletions src/Containers/MenuItemCard/MenuItemCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import React from 'react';
import styled from 'styled-components';
import { Main, MainInterface, Responsive, ResponsiveInterface } from '@Utils/BaseStyles';
import { transition } from '@Utils/Mixins';
// eslint-disable-next-line import/no-cycle
import { LoyaltyPoints, LimitedTimeBanner, SaleTag } from '../../index';

export interface MenuItemCardProps
extends MainInterface, ResponsiveInterface, React.HTMLAttributes<HTMLDivElement> {
LoyaltyPoints?: React.ReactElement;
LimitedTimeBanner?: React.ReactElement;
SaleTag?: React.ReactElement;
itemImage: string, // Image for the Menu Item Card, hosted on any server and converted to 350px x 200px
itemName: string, // Item name, heightFitContent adjusts the item card size to fit any text (keeping min size of 350px)
itemPrice: number, // Price of the item, will be adjusted by saleAmount and will reduce + round if above 1000
itemPriceLimit: number, // Limit before item price is divided by 1000, should be greater than 1000
animated?: boolean;
flat?: boolean;
widthFitContent?: boolean;
heightFitContent?: boolean;
sale?: boolean;
soldOut?: boolean;
loyaltyamount: number,
loyaltypointlimit: number,
saleAmount: number,
minsRemaining: number,
}

export const ItemCard: React.FC<MenuItemCardProps> = ({
children,
...props
}): React.ReactElement => <MenuItemCardBox {...props}>{children}</MenuItemCardBox>;

export const MenuItemCard: React.FC<MenuItemCardProps> = ({
animated,
flat,
widthFitContent,
heightFitContent,
sale,
soldOut,
itemImage,
itemName,
itemPrice,
itemPriceLimit,
saleAmount,
loyaltyamount,
loyaltypointlimit,
minsRemaining,
...props

}): React.ReactElement => (
<ItemCard {...props} itemImage={itemImage} itemName={itemName} itemPrice={itemPrice} animated={animated}
flat={flat} widthFitContent={widthFitContent} sale={sale} soldOut={soldOut} saleAmount = {saleAmount} itemPriceLimit = {itemPriceLimit}
loyaltyamount = {loyaltyamount} minsRemaining = {minsRemaining} loyaltypointlimit = {loyaltypointlimit} heightFitContent = {heightFitContent}>

<img src={itemImage} alt={itemName} style={{ width: 350, height: 200 }}/>
<ItemHeader>{itemName}</ItemHeader>
{ soldOut && <SoldOutBox>Sold Out</SoldOutBox>}

{ !!minsRemaining &&
<LimitedTimeBannerPosition> <LimitedTimeBanner minsRemaining={minsRemaining}/></LimitedTimeBannerPosition> }

{ !!loyaltyamount &&
<LoyaltyPointsPosition> <LoyaltyPoints loyaltyamount={loyaltyamount} loyaltypointlimit = {loyaltypointlimit} /></LoyaltyPointsPosition> }

{ !!saleAmount &&
<SaleTagPosition><SaleTag saleAmount={saleAmount}/></SaleTagPosition> }
Comment on lines +58 to +67
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you abstract this all out into a getMenuItemStatus function.

What happens if someone passes in two conflicting states. We will need to override.


{ sale
? <>
<SalePropsSlash>${itemPrice}</SalePropsSlash>
<OnSale>${itemPrice - saleAmount}</OnSale>
</>
: [ itemPrice >= itemPriceLimit
? <> <SaleProps1k>${getItemValue(itemPrice, itemPriceLimit)}K</SaleProps1k> </>
: <SaleProps>${itemPrice}</SaleProps>
]
}
</ItemCard>
);
/**
* Checks if the Item Price is greater than or equal to the item price limit
* Returns item price to the nearest tenth rounded
* Also reduces the amount by 1000, the K is added in the component
*/
function getItemValue(itemPrice: number, itemPriceLimit: number){
if(itemPrice >= itemPriceLimit)
return ((Math.round(itemPrice * .1) / .1) / 1000)
return itemPriceLimit };

const MenuItemCardBox = styled.div<MenuItemCardProps & MainInterface & ResponsiveInterface>`
position: relative;
width: 350px;
height: 350px;
min-height: 350px;
z-index: 1;
cursor: pointer;
box-shadow: ${({ flat, theme }): string => theme.depth[flat ? 0 : 1]};

${({ theme, ...props }): string => `
border-radius: ${theme.dimensions.radius};
font-family: ${theme.colors.background}};
background-color: white;
${Main({
...props,
})} `}

${({ animated, flat, theme }): string =>
animated ? ` ${transition(['box-shadow'])} &:hover {
box-shadow: ${theme.depth[flat ? 1 : 2]};
}` : ''}

${Responsive}

${({ soldOut }) =>
soldOut && `
opacity: 0.5;
cursor: not-allowed; `}

${({ widthFitContent }): string => `${widthFitContent ? 'width:fit-content;' : ''} `}
${({ heightFitContent }): string => `${heightFitContent ? 'height:fit-content;' : ''} `}
`;
const SoldOutBox = styled.div`
${({theme}):string => `
font-family: ${theme.font.family};
color: ${theme.colors.background}};
`}
position: absolute;
z-index: 2;
top: 0px;
background-color: rgba(48,48,48,48.0);
font-size: 25px;
text-align: center;
width: 350px;
height: 40px;
padding-top: 15px;
`;
const ItemHeader = styled.header`
font-weight: bold;
padding-left: 10px;
padding-bottom: 10px;
padding-right: 120px;
font-size: 35px;
`
const SaleProps = styled.header`
font-weight: bold;
position: absolute;
font-size: 30px;
text-align: right;
right: 10px;
top: 300px;
`
const SalePropsSlash = styled(SaleProps)`
text-decoration: line-through;
font-size: 25px;
opacity: .6;
top: 230px;
`
const SaleProps1k = styled(SaleProps)`
font-size: 35px;
${({theme}):string => `
color: ${theme.colors.ItemCardSaleGreen};
`}
`
const OnSale = styled.header`
position: absolute;
font-size: 35px;
text-align: right;
font-weight: bold;
${({theme}):string => `
color: ${theme.colors.primary};
`}
padding-right: 10px;
right: 10px;
top: 300px;
`
const LoyaltyPointsPosition = styled.div`
position: absolute;
top: 30px;
`
const SaleTagPosition = styled.div`
position: absolute;
right: 10px;
top: 53px;
`
const LimitedTimeBannerPosition = styled.div`
position: absolute;
top: 160px;
`
6 changes: 6 additions & 0 deletions src/Containers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,9 @@ export * from './TableHeaderCell/TableHeaderCell';
export * from './CustomerProfile/CustomerProfile';
export * from './CreatedDate/CreatedDate';
export * from './CRMRow/CRMRow';
// eslint-disable-next-line import/no-cycle
export * from './MenuItemCard/MenuItemCard'
// eslint-disable-next-line import/no-cycle
export * from './LimitedTimeBanner/LimitedTimeBanner'
export * from './LoyaltyPoints/LoyaltyPoints'
export * from './SaleTag/SaleTag'
7 changes: 7 additions & 0 deletions src/Themes/MainTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export interface MainThemeInterface extends ThemeTemplateInterface {
colors: {
primary: string;
text: string;
loyaltyText: string;
bannerBackgroundColor: string;
ItemCardSaleGreen: string;
input: {
default: string;
success: string;
Expand Down Expand Up @@ -31,6 +34,7 @@ export interface MainThemeInterface extends ThemeTemplateInterface {
chairTableBackground: string;
chairOccupiedBackground: string;
chairTableEditBackground: string;

};
}

Expand Down Expand Up @@ -60,6 +64,9 @@ export const MainTheme: MainThemeInterface = {
chairTableBackground: '#6c757d',
chairOccupiedBackground: '#EE2434',
chairTableEditBackground: '#C4C4C4',
loyaltyText: '#0000FF',
bannerBackgroundColor: 'rgba(0,0,0,0.5)',
ItemCardSaleGreen: '#04CC00',
PieChartColors: {
Red: '#FF0000',
Green: '#008000',
Expand Down
6 changes: 6 additions & 0 deletions src/Utils/positiveRounding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Rounds amount to the nearest positive integer above 0
* @param {number} amount - Number to round
* @returns {number} - Rounded amount above 0
*/
export const positiveRounding = (amount:number): number => (amount >= 1 ? Math.round(amount) : 1);