Skip to content
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
41 changes: 15 additions & 26 deletions components/DashboardShell.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
import React from 'react';
import {
Box,
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
Heading,
Button,
Flex,
Link,
Avatar,
Icon
} from '@chakra-ui/core';
import NextLink from 'next/link';
import { Box, Button, Flex, Link, Avatar, Icon } from '@chakra-ui/core';

import { useAuth } from '@/lib/auth';
import AddSiteModal from './AddSiteModal';
Expand All @@ -31,29 +21,28 @@ const DashboardShell = ({ children }) => {
w="full"
px={8}
>
<Flex>
<Icon name="logo" size="24px" mr={8} />
<Link mr={4}>Sites</Link>
<Link>Feedback</Link>
<Flex align="center">
<NextLink href="/" passHref>
<Link>
<Icon name="logo" size="24px" mr={8} />
</Link>
</NextLink>
<NextLink href="/dashboard" passHref>
<Link mr={4}>Sites</Link>
</NextLink>
<NextLink href="/feedback" passHref>
<Link>Feedback</Link>
</NextLink>
</Flex>
<Flex justifyContent="center" alignItems="center">
<Button variant="ghost" mr={2} onClick={() => signout()}>
Log Out
</Button>
<Avatar size="sm" src={user.photoUrl} />
<Avatar size="sm" src={user ?.photoUrl} />
</Flex>
</Flex>
</Flex>
<Flex margin="0 auto" direction="column" maxW="1250px" px={8}>
<Breadcrumb>
<BreadcrumbItem>
<BreadcrumbLink>Sites</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
<Flex justifyContent="space-between">
<Heading mb={8}>My Sites</Heading>
<AddSiteModal>+ Add Site</AddSiteModal>
</Flex>
{children}
</Flex>
</Box>
Expand Down
74 changes: 74 additions & 0 deletions components/DeleteFeedbackButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useState, useRef } from 'react';
import { mutate } from 'swr';
import {
AlertDialog,
AlertDialogBody,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogContent,
AlertDialogOverlay,
IconButton,
Button
} from '@chakra-ui/core';

import { deleteFeedback } from '@/lib/db';
import { useAuth } from '@/lib/auth';

const DeleteFeedbackButton = ({ feedbackId }) => {
const [isOpen, setIsOpen] = useState();
const cancelRef = useRef();
const auth = useAuth();

const onClose = () => setIsOpen(false);
const onDelete = () => {
deleteFeedback(feedbackId);
mutate(
['/api/feedback', auth.user.token],
async (data) => {
return {
feedback: data.feedback.filter(
(feedback) => feedback.id !== feedbackId
)
};
},
false
);
onClose();
};

return (
<>
<IconButton
aria-label="Delete feedback"
icon="delete"
variant="ghost"
onClick={() => setIsOpen(true)}
/>
<AlertDialog
isOpen={isOpen}
leastDestructiveRef={cancelRef}
onClose={onClose}
>
<AlertDialogOverlay />
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
Delete Feedback
</AlertDialogHeader>
<AlertDialogBody>
Are you sure? You can't undo this action afterwards.
</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose}>
Cancel
</Button>
<Button variantColor="red" onClick={onDelete} ml={3}>
Delete
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
};

export default DeleteFeedbackButton;
43 changes: 43 additions & 0 deletions components/FeedbackTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { Box, Code, Switch, IconButton } from '@chakra-ui/core';

import { Table, Tr, Th, Td } from './Table';
import DeleteFeedbackButton from './DeleteFeedbackButton';

const FeedbackTable = (props) => {
return (
<Table>
<thead>
<Tr>
<Th>Name</Th>
<Th>Feedback</Th>
<Th>Route</Th>
<Th>Visible</Th>
<Th width="50px">{''}</Th>
</Tr>
</thead>
<tbody>
{props.feedback.map((feedback) => (
<Box as="tr" key={feedback.id}>
<Td fontWeight="medium">{feedback.author}</Td>
<Td>{feedback.text}</Td>
<Td>
<Code>{feedback.route || '/'}</Code>
</Td>
<Td>
<Switch
color="green"
defaultIsChecked={feedback.status === 'active'}
/>
</Td>
<Td>
<DeleteFeedbackButton feedbackId={feedback.id} />
</Td>
</Box>
))}
</tbody>
</Table>
);
};

export default FeedbackTable;
23 changes: 23 additions & 0 deletions components/FeedbackTableHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
Heading,
Flex
} from '@chakra-ui/core';

const FeedbackTableHeader = () => (
<>
<Breadcrumb>
<BreadcrumbItem>
<BreadcrumbLink>Feedback</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
<Flex justifyContent="space-between">
<Heading mb={8}>My Feedback</Heading>
</Flex>
</>
);

export default FeedbackTableHeader;
45 changes: 45 additions & 0 deletions components/FeedbackTableSkeleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { Box, Skeleton } from '@chakra-ui/core';
import { Table, Tr, Th, Td } from './Table';

const SkeletonRow = ({ width }) => (
<Box as="tr">
<Td>
<Skeleton height="10px" w={width} my={4} />
</Td>
<Td>
<Skeleton height="10px" w={width} my={4} />
</Td>
<Td>
<Skeleton height="10px" w={width} my={4} />
</Td>
<Td>
<Skeleton height="10px" w={width} my={4} />
</Td>
</Box>
);

const FeedbackTableSkeleton = () => {
return (
<Table>
<thead>
<Tr>
<Th>Name</Th>
<Th>Feedback</Th>
<Th>Route</Th>
<Th>Visible</Th>
<Th width="50px">{''}</Th>
</Tr>
</thead>
<tbody>
<SkeletonRow width="75px" />
<SkeletonRow width="125px" />
<SkeletonRow width="50px" />
<SkeletonRow width="100px" />
<SkeletonRow width="75px" />
</tbody>
</Table>
);
};

export default FeedbackTableSkeleton;
2 changes: 1 addition & 1 deletion components/SiteTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const SiteTable = ({ sites }) => {
</Td>
<Td>
<NextLink href="/p/[siteId]" as={`/p/${site.id}`} passHref>
<Link>View Feedback</Link>
<Link color="blue.500" fontWeight="medium">View Feedback</Link>
</NextLink>
</Td>
<Td>{format(parseISO(site.createdAt), 'PPpp')}</Td>
Expand Down
26 changes: 26 additions & 0 deletions components/SiteTableHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
Heading,
Flex
} from '@chakra-ui/core';

import AddSiteModal from './AddSiteModal';

const SiteTableHeader = () => (
<>
<Breadcrumb>
<BreadcrumbItem>
<BreadcrumbLink>Sites</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
<Flex justifyContent="space-between">
<Heading mb={8}>My Sites</Heading>
<AddSiteModal>+ Add Site</AddSiteModal>
</Flex>
</>
);

export default SiteTableHeader;
8 changes: 8 additions & 0 deletions lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ function useProvideAuth() {
.then((response) => handlerUser(response.user));
};

const signinWithGoogle = () => {
return firebase
.auth()
.signInWithPopup(new firebase.auth.GoogleAuthProvider())
.then((response) => handleUser(response.user));
};

const signout = () => {
return firebase
.auth()
Expand All @@ -60,6 +67,7 @@ function useProvideAuth() {
return {
user,
signinWithGithub,
signinWithGoogle,
signout
};
}
Expand Down
16 changes: 16 additions & 0 deletions lib/db-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,19 @@ export async function getUserSites(uid) {

return { sites };
}


export async function getUserFeedback(uid) {
const snapshot = await db
.collection('feedback')
.where('authorId', '==', uid)
.get();

const feedback = [];

snapshot.forEach((doc) => {
feedback.push({ id: doc.id, ...doc.data() });
});

return { feedback };
}
4 changes: 4 additions & 0 deletions lib/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ export function createSite(data) {
export function createFeedback(data) {
return firestore.collection('feedback').add(data);
}

export function deleteFeedback(id) {
return firestore.collection('feedback').doc(id).delete();
}
13 changes: 13 additions & 0 deletions pages/api/feedback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { auth } from '@/lib/firebase-admin';
import { getUserFeedback } from '@/lib/db-admin';

export default async (req, res) => {
try {
const { uid } = await auth.verifyIdToken(req.headers.token);
const { feedback } = await getUserFeedback(uid);

res.status(200).json({ feedback });
} catch (error) {
res.status(500).json({ error });
}
};
11 changes: 9 additions & 2 deletions pages/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,26 @@ import EmptyState from '@/components/EmptyState';
import DashboardShell from '@/components/DashboardShell';
import SiteTableSkeleton from '@/components/SiteTableSkeleton';
import SiteTable from '@/components/SiteTable';
import SiteTableHeader from '@/components/SiteTableHeader';
import fetcher from '@/utils/fetcher';

const Dashboard = () => {
const { user } = useAuth();
const { data, error } = useSWR(user ? ['/api/sites', user.token] : null, fetcher);

if (!data) {
return <SiteTableSkeleton />;
return (
<DashboardShell>
<SiteTableHeader />
<SiteTableSkeleton />
</DashboardShell>
);
}

return (
<DashboardShell>
{data ?.sites ? <SiteTable sites={data.sites} /> : <EmptyState />};
<SiteTableHeader />
{data.sites.length ? <SiteTable sites={data.sites} /> : <EmptyState />};
</DashboardShell>
);
};
Expand Down
Loading