Skip to content
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
6 changes: 0 additions & 6 deletions Frontend/speedcart-react/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ body {
box-sizing: border-box;
}

.main-content {
flex: 1;
overflow-y: auto; /* Allow content area to scroll */
max-height: calc(100vh - 60px); /* Adjust based on header and footer height */
}

#policyFooter a {
text-decoration: none;
color: white;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
.labelContainer {
display: flex;
align-items: center; /* Vertically center the checkbox and label */
justify-content: center; /* Horizontally center the checkbox and label */
position: relative;
cursor: pointer;
user-select: none;
text-align: center; /* Ensures text is also centered if used */
}

.flex {
display: flex;
}

.inlineFlex {
display: inline-flex;
}

.input {
position: absolute;
opacity: 0;
Expand All @@ -22,12 +28,15 @@
width: 16px;
background-color: #eee;
border-radius: 4px;
margin-right: 8px;
display: flex; /* Use flex to center the checkmark visually */
align-items: center; /* Vertical center */
justify-content: center; /* Horizontal center */
}

.marginRightDistance {
margin-right: 8px;
}

.labelContainer:hover .checkmark {
background-color: #ccc;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import styles from './CustomCheckbox.module.css';

const CustomCheckbox = ({ name = '', className = '', checked = false, onChange = null, disabled = false, children = null}) => {
const CustomCheckbox = ({ name = '', className = '', flexType = 'inlineFlex', checked = false, onChange = null, disabled = false, children = null}) => {
return (
<label className={`${styles.labelContainer} ${className} ${disabled ? styles.disabled : ''}`}>
<label className={`${styles.labelContainer} ${flexType === 'flex' ? styles.flex : styles.inlineFlex} ${className} ${disabled ? styles.disabled : ''}`}>
<input
type="checkbox"
className={styles.input}
Expand All @@ -12,7 +12,7 @@ const CustomCheckbox = ({ name = '', className = '', checked = false, onChange =
disabled={disabled}
name={name}
/>
<span className={styles.checkmark}></span>
<span className={`${styles.checkmark} ${children && styles.marginRightDistance}`}></span>
{children}
</label>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.mainContent {
flex: 1;
overflow-y: auto; /* Allow content area to scroll */
max-height: calc(100vh - 60px); /* Adjust based on header and footer height */
}
18 changes: 18 additions & 0 deletions Frontend/speedcart-react/src/components/PageLayout/PageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// src/components/PageLayout.tsx
import React from 'react';
import StatusModal from '@components/StatusModal';

import styles from './PageLayout.module.css';

const PageLayout = ({ children, status = null, modalProps = null, className=''}) => {
return (
<>
<main className={`${styles.mainContent} ${className}`}>
{children}
</main>
{modalProps && <StatusModal status={status} {...modalProps} />}
</>
);
};

export default PageLayout;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './PageLayout';
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// src/components/StatusModal.js
import React, { useEffect, useState } from 'react';
import styles from './StatusModal.module.css';
import { RequestStatus } from '@constants/enums';
Expand Down
27 changes: 15 additions & 12 deletions Frontend/speedcart-react/src/pages/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';

import { FaTrash, FaEdit, FaShare, FaClipboard } from 'react-icons/fa';

import { useAuth, fetchOwnedShoppingLists, fetchSharedShoppingLists, deleteShoppingList, createShareLink, AuthContextType } from 'shared';

import PageLayout from '@components/PageLayout';
import Modal from '@components/Modal';
import StatusModal from '@components/StatusModal';
import CustomCheckbox from '@components/CustomCheckbox';

import { RequestStatus } from '@constants/enums';
Expand Down Expand Up @@ -181,7 +182,14 @@ function Dashboard() {

return (
<>
<main className={`main-content`}>
<PageLayout
status={deletionStatus}
modalProps={{
loadingText:'Attempting deletion...',
successText:'Deletion successful! Updating your list of shopping lists...',
errorText:`Deletion failed! ${error}`
}}
>
<div className={styles.searchContainer}>
<label className={styles.caseSensitiveLabel}>
<input
Expand Down Expand Up @@ -300,16 +308,16 @@ function Dashboard() {
(read is always the bare minimum).
</section>
<section>
<CustomCheckbox disabled={true} checked={true}>
<CustomCheckbox disabled={true} checked={true} flexType={'flex'}>
Read
</CustomCheckbox>
<CustomCheckbox checked={canUpdate} onChange={() => {
<CustomCheckbox checked={canUpdate} flexType={'flex'} onChange={() => {
// Invert the current state
setCanUpdate(!canUpdate);
}}>
Update
</CustomCheckbox>
<CustomCheckbox checked={canDelete} onChange={() => {
<CustomCheckbox checked={canDelete} flexType={'flex'} onChange={() => {
// Invert the current state
setCanDelete(!canDelete);
}}>
Expand All @@ -334,12 +342,7 @@ function Dashboard() {
) : <Link to="/login" className={styles.loginBtn}>Go sign in</Link>
}
</div>
</main>
<StatusModal status={deletionStatus}
loadingText='Attempting deletion...'
successText='Deletion successful! Updating your list of shopping lists...'
errorText={`Deletion failed! ${error}`}
/>
</PageLayout>
</>
);
}
Expand Down
5 changes: 3 additions & 2 deletions Frontend/speedcart-react/src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useEffect } from 'react';

import PageLayout from '@components/PageLayout';
import SiteLogo from '@components/SiteLogo';
import TransitionSection from '@components/TransitionSection';

Expand All @@ -17,7 +18,7 @@ const Home: React.FC<any> = (props) => {
}, []);

return (
<main id={props.id} className={`main-content`}>
<PageLayout>
<TransitionSection additionalClasses="centerAlignment" showClasses={[styles.inView]} hiddenClasses={[styles.outOfView]}>
<SiteLogo />
<h1 className={styles.heading}>Welcome to SpeedCart</h1>
Expand Down Expand Up @@ -74,7 +75,7 @@ const Home: React.FC<any> = (props) => {
</p>
</div>
</TransitionSection>
</main>
</PageLayout>
);
}

Expand Down
27 changes: 13 additions & 14 deletions Frontend/speedcart-react/src/pages/Login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { GoogleLogin } from '@react-oauth/google';

import { useAuth } from 'shared';

import StatusModal from '@components/StatusModal';
import PageLayout from '@components/PageLayout';

import { RequestStatus } from '@constants/enums';
import { AppRoute } from '@constants/routes';
Expand Down Expand Up @@ -56,26 +56,25 @@ function Login() {
};

return (
<>
<main className={`${styles.loginContainer} main-content`}>
<PageLayout
status={loginStatus}
modalProps={{
loadingText: 'Verifying login token...',
successText: `Login successful! Redirecting to ${redirectPageName}...`,
errorText: `Login verification failed! ${loginError}`
}}
>
<section className={styles.loginContainer}>
{isAuthenticated ? (
<>
<button onClick={logout} className={styles.logoutBtn}>Logout</button>
</>

<button onClick={logout} className={styles.logoutBtn}>Logout</button>
) : (
<GoogleLogin
onSuccess={handleLoginSuccess}
onError={handleLoginError}
/>
)}
</main>
<StatusModal status={loginStatus}
loadingText='Verifying login token...'
successText={`Login successful! Redirecting to ${redirectPageName}...`}
errorText={`Login verification failed! ${loginError}`}
/>
</>
</section>
</PageLayout>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; // Necessary for redirects

import { useAuth, AuthContextType } from 'shared';

import PageLayout from '@components/PageLayout';
import SaveButton from '@components/SaveButton';
import AddShoppingListItemButton from '@components/AddShoppingListItemButton';
import StatusModal from '@components/StatusModal'; // Import StatusModal to provide UI info on list save status
import ShoppingListSection from '@components/ShoppingListSection';

import { ShoppingListProvider, useShoppingListContext } from '@customHooks/ShoppingListContext';
Expand Down Expand Up @@ -71,7 +72,14 @@ const NewShoppingList: React.FC = () => {

return (
<>
<main className='main-content'>
<PageLayout
status={saveStatus}
modalProps={{
loadingText:'Loading...',
successText:'Save successful! Redirecting...',
errorText:`Save failed! ${saveError}`
}}
>
<form className={`${styles.shoppingList}`} onSubmit={handleSubmit}>
<div className={styles.inputGroup}>
<label htmlFor="listTitle">Title of new list:</label>
Expand Down Expand Up @@ -103,12 +111,7 @@ const NewShoppingList: React.FC = () => {
crudMode={crudMode}
/>
</form>
</main>
<StatusModal status={saveStatus}
loadingText='Loading...'
successText='Save successful! Redirecting...'
errorText={`Save failed! ${saveError}`}
/>
</PageLayout>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React, { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid'; // Import uuid library for unique item identification
import { useParams } from 'react-router-dom';

import {
fetchGroceryItems,
fetchShoppingList,
} from 'shared';

import PageLayout from '@components/PageLayout';
import SaveButton from '@components/SaveButton';
import AddShoppingListItemButton from '@components/AddShoppingListItemButton';
import StatusModal from '@components/StatusModal';
import ShoppingListSection from '@components/ShoppingListSection';

import { ShoppingListProvider, useShoppingListContext } from '@customHooks/ShoppingListContext';
Expand Down Expand Up @@ -141,16 +140,23 @@ const ShoppingListDetail = () => {
};

if (loading) {
return <main className={`main-content`}>Loading...</main>;
return <PageLayout>Loading...</PageLayout>;
}

if (error) {
return <main className={`main-content`}>Error: {error}</main>;
return <PageLayout>Error: {error}</PageLayout>;
}

return (
<>
<main className={`main-content ${styles.flexCenter}`}>
<PageLayout className={styles.flexCenter}
status={editStatus}
modalProps={{
loadingText:'Loading...',
successText:'Edit save successful! Refreshing page...',
errorText:`Edit save failed! ${error}`
}}
>
<form onSubmit={handleSubmit} className={`${styles.innerContentArea} ${styles.form}`}>
<div className={styles.formHeader}>
<label htmlFor="editModeToggle">
Expand Down Expand Up @@ -227,12 +233,7 @@ const ShoppingListDetail = () => {
)}
</div>
</form>
</main>
<StatusModal status={editStatus}
loadingText='Loading...'
successText='Edit save successful! Refreshing page...'
errorText={`Edit save failed! ${error}`}
/>
</PageLayout>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { GoogleLogin } from '@react-oauth/google';

import { useAuth, createSharingPermissions } from 'shared';

import PageLayout from "@components/PageLayout";

import { AppRoute } from "@constants/routes";


Expand Down Expand Up @@ -81,7 +83,7 @@ function ShoppingListShare() {
};

return (
<main className='main-content'>
<PageLayout>
{/* Make sure user is signed in */}
{!isAuthenticated ? (
<>
Expand All @@ -96,7 +98,7 @@ function ShoppingListShare() {
{shareInteractionStatus}
</>
)}
</main>
</PageLayout>
);
}

Expand Down