Skip to content

Commit

Permalink
Activity feed page (#47)
Browse files Browse the repository at this point in the history
* #46 Add initial activity feed page
* #46 Update activity feed POC to match new schema
* Add npm start alias for npm run dev
* #46 Simplify the design of the activity feed
* #46 Change the style of the feed to use cards
* #46 Add activity feed link to mobile nav
* #46 Fix attribute formatting
  • Loading branch information
danielemery authored Jul 21, 2024
1 parent 01b60f7 commit 196c3fb
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 0 deletions.
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"node": "v20.12.2"
},
"scripts": {
"start": "npm run dev",
"dev": "doppler run -- npm run init-local && vite",
"build": "tsc && vite build",
"preview": "vite preview",
Expand All @@ -20,6 +21,7 @@
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"classnames": "^2.3.1",
"date-fns": "^3.6.0",
"docker-react": "^0.0.3",
"graphql": "^16.8.1",
"joi": "^17.6.0",
Expand Down
6 changes: 6 additions & 0 deletions src/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export default function NavigationBar({
</Link>
{isAuthenticated && (
<>
<Link className='hidden lg:block' to='/feed'>
<NavigationBarItem>Activity</NavigationBarItem>
</Link>
{canUploadQuiz && (
<Link className='hidden lg:block' to='/quiz/create'>
<NavigationBarItem>Upload Quiz</NavigationBarItem>
Expand Down Expand Up @@ -71,6 +74,9 @@ export default function NavigationBar({
{isAuthenticated && (
<nav className='lg:hidden p-2 bg-slate-500 text-white flex justify-between'>
<>
<Link to='/feed'>
<NavigationBarItem>Activity</NavigationBarItem>
</Link>
{canUploadQuiz && (
<Link to='/quiz/create'>
<NavigationBarItem>Upload Quiz</NavigationBarItem>
Expand Down
2 changes: 2 additions & 0 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import QuizDetails from './QuizDetails';
import { useQuizlord } from './QuizlordProvider';
import Button from './components/Button';
import Loader from './components/Loader';
import ActivityFeed from './pages/feed/ActivityFeed';
import QuizList from './pages/list/QuizList';
import QuizStatistics from './pages/statistics/QuizStatistics';
import { userCanPerformAction } from './services/authorization';
Expand Down Expand Up @@ -55,6 +56,7 @@ export function App() {
<Route path='/quiz/:id' element={<QuizDetails />} />
<Route path='/quiz/:id/enter' element={<EnterQuizResults />} />
<Route path='/stats' element={<QuizStatistics />} />
<Route path='/feed' element={<ActivityFeed />} />
</Routes>
)}
</div>
Expand Down
25 changes: 25 additions & 0 deletions src/hooks/useActivityFeed.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useQuery } from '@apollo/client';

import { ACTIVITY_FEED } from '../queries/feed';
import { User } from '../types/user';

// TODO this should be generated from the GraphQL schema
export interface RecentActivityItem {
date: Date;
text: string;
resourceId: string;
users: User[];
}

export function useActivityFeed(): {
loading: boolean;
data: { activityFeed: RecentActivityItem[] } | undefined;
refetch: () => void;
} {
const { loading, data, refetch } = useQuery(ACTIVITY_FEED, {
fetchPolicy: 'network-only',
notifyOnNetworkStatusChange: true,
});

return { loading, data, refetch };
}
38 changes: 38 additions & 0 deletions src/pages/feed/ActivityFeed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { intlFormatDistance } from 'date-fns';

import Loader from '../../components/Loader';
import { userIdentifier } from '../../helpers';
import { RecentActivityItem, useActivityFeed } from '../../hooks/useActivityFeed.hook';

export default function ActivityFeed() {
const { data, loading } = useActivityFeed();

if (loading || !data) {
return <Loader message='Loading recent activities...' />;
}

return (
<div>
{data?.activityFeed.map((activity) => (
<ActivityCard key={activity.resourceId} recentlyActivityItem={activity} />
))}
</div>
);
}

export function ActivityCard({ recentlyActivityItem }: { recentlyActivityItem: RecentActivityItem }) {
return (
<div className='bg-white m-2 p-2 rounded-lg border-solid border-2'>
<div>
<div className='flex justify-between'>
<div className='font-bold'>{recentlyActivityItem.users.map((u) => userIdentifier(u)).join(', ')}</div>
<i className='hidden lg:block'>{intlFormatDistance(recentlyActivityItem.date, new Date())}</i>
</div>
</div>
<div>{recentlyActivityItem.text}</div>
<div className='lg:hidden'>
<i>{intlFormatDistance(recentlyActivityItem.date, new Date())}</i>
</div>
</div>
);
}
15 changes: 15 additions & 0 deletions src/queries/feed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { gql } from '@apollo/client';

export const ACTIVITY_FEED = gql`
query GetActivityFeed {
activityFeed {
date
text
resourceId
users {
name
email
}
}
}
`;

0 comments on commit 196c3fb

Please sign in to comment.