mirror of
https://github.com/rowyio/rowy.git
synced 2026-07-13 05:48:53 +02:00
favorite tables
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
import React, { useEffect, useState, useContext } from "react";
|
||||
import { auth, db } from "../firebase";
|
||||
import firebase from "firebase/app";
|
||||
import useDoc from "hooks/useDoc";
|
||||
|
||||
interface AppContextInterface {
|
||||
currentUser: firebase.User | null | undefined;
|
||||
userDoc: any;
|
||||
}
|
||||
|
||||
export const AppContext = React.createContext<AppContextInterface>({
|
||||
currentUser: undefined,
|
||||
userDoc: undefined,
|
||||
});
|
||||
|
||||
export const useAppContext = () => useContext(AppContext);
|
||||
@@ -25,23 +28,21 @@ export const AppProvider: React.FC<IAppProviderProps> = ({
|
||||
firebase.User | null | undefined
|
||||
>();
|
||||
|
||||
const [userDoc, dispatchUserDoc] = useDoc({});
|
||||
useEffect(() => {
|
||||
auth.onAuthStateChanged(auth => {
|
||||
setCurrentUser(auth);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const getUserTheme = async (currentUser: firebase.User) => {
|
||||
const userDoc = await db
|
||||
.collection("_FT_USERS")
|
||||
.doc(currentUser.uid)
|
||||
.get();
|
||||
if (userDoc.exists) {
|
||||
const userDocData = userDoc.data();
|
||||
if (userDocData && userDocData.theme) {
|
||||
setTheme(userDocData.theme);
|
||||
}
|
||||
} else {
|
||||
useEffect(() => {
|
||||
if (userDoc.doc) {
|
||||
setTheme(userDoc.doc.theme);
|
||||
} else if (
|
||||
!userDoc.doc &&
|
||||
!userDoc.loading &&
|
||||
userDoc.path &&
|
||||
currentUser
|
||||
) {
|
||||
const userFields = ["email", "displayName", "photoURL", "phoneNumber"];
|
||||
const userData = userFields.reduce((acc, curr) => {
|
||||
if (currentUser[curr]) {
|
||||
@@ -49,30 +50,30 @@ export const AppProvider: React.FC<IAppProviderProps> = ({
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
db.collection("_FT_USERS")
|
||||
.doc(currentUser.uid)
|
||||
.set(
|
||||
{
|
||||
user: userData,
|
||||
theme: {
|
||||
palette: {
|
||||
primary: { main: "#ef4747" },
|
||||
},
|
||||
db.doc(userDoc.path).set(
|
||||
{
|
||||
user: userData,
|
||||
theme: {
|
||||
palette: {
|
||||
primary: { main: "#ef4747" },
|
||||
},
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
}
|
||||
};
|
||||
}, [userDoc]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser) {
|
||||
getUserTheme(currentUser);
|
||||
dispatchUserDoc({ path: `_FT_USERS/${currentUser.uid}` });
|
||||
}
|
||||
}, [currentUser]);
|
||||
|
||||
return (
|
||||
<AppContext.Provider
|
||||
value={{
|
||||
userDoc: { state: userDoc, dispatch: dispatchUserDoc },
|
||||
currentUser,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import React from "react";
|
||||
import _groupBy from "lodash/groupBy";
|
||||
|
||||
import _find from "lodash/find";
|
||||
import {
|
||||
createStyles,
|
||||
makeStyles,
|
||||
Container,
|
||||
Grid,
|
||||
Link,
|
||||
Button,
|
||||
Typography,
|
||||
Divider,
|
||||
Checkbox,
|
||||
} from "@material-ui/core";
|
||||
import Favorite from "@material-ui/icons/Favorite";
|
||||
import FavoriteBorder from "@material-ui/icons/FavoriteBorder";
|
||||
import SecurityIcon from "@material-ui/icons/Security";
|
||||
|
||||
import AppBar from "components/AppBar";
|
||||
import Loading from "components/Loading";
|
||||
import EmptyState from "components/EmptyState";
|
||||
import StyledCard from "components/StyledCard";
|
||||
import CreateTableDialog from "components/CreateTableDialog";
|
||||
|
||||
import routes from "constants/routes";
|
||||
import { useFiretableContext } from "contexts/firetableContext";
|
||||
|
||||
import { useAppContext } from "contexts/appContext";
|
||||
import { DocActions } from "hooks/useDoc";
|
||||
const useStyles = makeStyles(theme =>
|
||||
createStyles({
|
||||
root: { minHeight: "100vh", paddingBottom: theme.spacing(8) },
|
||||
@@ -70,11 +71,57 @@ const useStyles = makeStyles(theme =>
|
||||
const TablesView = () => {
|
||||
const classes = useStyles();
|
||||
const { sections, createTable, userClaims } = useFiretableContext();
|
||||
const { userDoc } = useAppContext();
|
||||
|
||||
const favs = userDoc.state.doc?.favoriteTables
|
||||
? userDoc.state.doc.favoriteTables
|
||||
: [];
|
||||
|
||||
const TableCard = props => {
|
||||
const { table } = props;
|
||||
const checked = Boolean(_find(favs, table));
|
||||
return (
|
||||
<Grid key={table.name} item xs={12} sm={6} md={4}>
|
||||
<StyledCard
|
||||
className={classes.card}
|
||||
overline={table.section}
|
||||
title={table.name}
|
||||
bodyContent={table.description}
|
||||
primaryLink={{
|
||||
to: `${routes.table}/${table.collection}${
|
||||
table.regional &&
|
||||
userClaims?.regions &&
|
||||
!userClaims?.regions.includes("GLOBAL")
|
||||
? `?filters=%5B%7B%22key%22%3A%22region%22%2C%22operator%22%3A%22%3D%3D%22%2C%22value%22%3A%22${userClaims?.regions[0]}%22%7D%5D`
|
||||
: ""
|
||||
}`,
|
||||
label: "Open",
|
||||
}}
|
||||
secondaryAction={
|
||||
<Checkbox
|
||||
onClick={e => {
|
||||
userDoc.dispatch({
|
||||
action: DocActions.update,
|
||||
data: {
|
||||
favoriteTables: checked
|
||||
? favs.filter(t => t.collection !== table.collection)
|
||||
: [...favs, table],
|
||||
},
|
||||
});
|
||||
}}
|
||||
checked={checked}
|
||||
icon={<FavoriteBorder />}
|
||||
checkedIcon={<Favorite />}
|
||||
name="checkedH"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<main className={classes.root}>
|
||||
<AppBar />
|
||||
|
||||
<Container>
|
||||
{(!userClaims?.roles || userClaims.roles.length === 0) && (
|
||||
<EmptyState
|
||||
@@ -99,7 +146,22 @@ const TablesView = () => {
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{favs.length !== 0 && (
|
||||
<div key={"favorites"} className={classes.section}>
|
||||
<Typography variant="overline">favorites</Typography>
|
||||
<Divider className={classes.divider} />
|
||||
<Grid
|
||||
container
|
||||
spacing={4}
|
||||
justify="flex-start"
|
||||
className={classes.cardGrid}
|
||||
>
|
||||
{favs.map(table => (
|
||||
<TableCard table={table} />
|
||||
))}
|
||||
</Grid>
|
||||
</div>
|
||||
)}
|
||||
{sections ? (
|
||||
Object.keys(sections).map(sectionName => (
|
||||
<div key={sectionName} className={classes.section}>
|
||||
@@ -114,24 +176,7 @@ const TablesView = () => {
|
||||
className={classes.cardGrid}
|
||||
>
|
||||
{sections[sectionName].map(table => (
|
||||
<Grid key={table.name} item xs={12} sm={6} md={4}>
|
||||
<StyledCard
|
||||
className={classes.card}
|
||||
overline={sectionName}
|
||||
title={table.name}
|
||||
bodyContent={table.description}
|
||||
primaryLink={{
|
||||
to: `${routes.table}/${table.collection}${
|
||||
table.regional &&
|
||||
userClaims?.regions &&
|
||||
!userClaims?.regions.includes("GLOBAL")
|
||||
? `?filters=%5B%7B%22key%22%3A%22region%22%2C%22operator%22%3A%22%3D%3D%22%2C%22value%22%3A%22${userClaims?.regions[0]}%22%7D%5D`
|
||||
: ""
|
||||
}`,
|
||||
label: "Open",
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<TableCard table={table} />
|
||||
))}
|
||||
</Grid>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user