Skip to content

Commit

Permalink
Add React Query (#237)
Browse files Browse the repository at this point in the history
  • Loading branch information
0916dhkim committed Nov 1, 2023
1 parent 6d2b24c commit 63183a7
Show file tree
Hide file tree
Showing 27 changed files with 251 additions and 190 deletions.
6 changes: 6 additions & 0 deletions server/package-lock.json

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

1 change: 1 addition & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-session": "^1.17.3",
"tiny-invariant": "^1.3.1",
"tsx": "^3.14.0",
"zod": "^3.21.4"
},
Expand Down
3 changes: 3 additions & 0 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import router from './modules/routes';
import session from 'express-session';
import { env } from './utils/env';
import path from 'node:path';
import invariant from 'tiny-invariant';

const WEB_DIST_PATH = path.resolve(__dirname, '../../web/dist');

const app = express();
const port = 3000;

invariant(env.SESSION_SECRET);

// middlewares
app.use(express.static(WEB_DIST_PATH));
app.use(express.json());
Expand Down
13 changes: 13 additions & 0 deletions server/src/modules/auth/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ import { loginReqSchema, registerReqSchema } from './validations';
import authService from './service';

const authController = {
getCurrentUser: async (req: Request, res: Response, next: NextFunction) => {
try {
if (req.session.user == null) {
return null;
}
const { id } = req.session.user;
const user = await authService.getUser(id);
return user;
} catch (e) {
next(e);
}
},

login: async (req: Request, res: Response, next: NextFunction) => {
try {
const { body } = await validationParser(loginReqSchema, req);
Expand Down
1 change: 1 addition & 0 deletions server/src/modules/auth/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import authController from './controller';

const authRouter = Router();

authRouter.get('/user', authController.getCurrentUser);
authRouter.post('/login', authController.login);
authRouter.post('/register', authController.register);
authRouter.get('/logout', authController.logout);
Expand Down
13 changes: 11 additions & 2 deletions server/src/modules/auth/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ import * as bcrypt from 'bcrypt';
import { AuthInfo } from 'express-session';

const authService = {
getUser: async (id: string) => {
try {
const user = await prisma.user.findUnique({ where: { id } });
return user;
} catch {
return null;
}
},

/**
* Takes in an email and password and checks if the credentials match any user
* in the database. If successful the user auth info is returned else an Unauthorized error
Expand All @@ -26,8 +35,8 @@ const authService = {
register: async (
email: string,
password: string,
firstname: string,
lastname: string,
firstname?: string,
lastname?: string,
phone?: string,
): Promise<AuthInfo> => {
const existingUser = await prisma.user.findUnique({
Expand Down
6 changes: 3 additions & 3 deletions server/src/modules/community-event/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { updateCommunityEventReq } from './validations';

export default {
default: (
communityEvent: CommunityEvent & { organizer: User },
communityEvent: CommunityEvent & { organizer?: User | null },
): CommunityEventResponse => ({
id: communityEvent.id,
eventType: communityEvent.eventType,
ideaConfirmed: communityEvent.ideaConfirmed,
organizer: communityEvent.organizerId,
organizer: communityEvent.organizer,
date: communityEvent.date,
inPersonEvent: communityEvent.inPersonEvent,
onlineEvent: communityEvent.onlineEvent,
Expand All @@ -21,7 +21,7 @@ export default {
venueContactEmail: communityEvent.venueContactEmail,
eventAnnounced: communityEvent.announcementPosted,
signUpFormSent: communityEvent.signUpFormSent,
numVolunteersNeeded: communityEvent.volunteersNeeded,
volunteersNeeded: communityEvent.volunteersNeeded,
volunteerRequestsSent: communityEvent.volunteerRequestsSent,
}),

Expand Down
12 changes: 4 additions & 8 deletions server/src/modules/community-event/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@ import {
import { Modify } from '../../utils/types';

export type CommunityEvent = CommunityEventPrisma & {
eventType: EventType;
organizer: User;
eventType?: EventType | null;
organizer?: User | null;
};

export type CommunityEventResponse = Modify<
Omit<
CommunityEvent,
'typeId' | 'organizerId' | 'announcementPosted' | 'volunteersNeeded'
>,
Omit<CommunityEvent, 'typeId' | 'organizerId' | 'announcementPosted'>,
{
organizer: string;
organizer?: User | null;
eventAnnounced: boolean;
numVolunteersNeeded: number;
}
>;
3 changes: 3 additions & 0 deletions server/src/modules/event-type/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const eventTypeController = {
await isAuthenticated(req.session);
const { id } = req.params;
const result = await eventTypeService.findById(id);
if (result == null) {
return res.sendStatus(404);
}
res.json({ data: eventTypeSerializer.default(result) });
} catch (e) {
next(e);
Expand Down
4 changes: 1 addition & 3 deletions server/src/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ export class BadRequestError extends ApplicationError {
issues: unknown[];
constructor(message?: string, issues?: unknown[]) {
super(message || 'VALIDATION ERROR', 400);
if (issues) {
this.issues = issues;
}
this.issues = issues ?? [];
}
}

Expand Down
2 changes: 1 addition & 1 deletion server/src/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ export async function validationParser<T extends AnyZodObject>(
if (err instanceof ZodError) {
throw new BadRequestError('', err.issues);
}
throw new BadRequestError(err.message);
throw new BadRequestError(String(err));
}
}
8 changes: 2 additions & 6 deletions server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"noUnusedLocals": true,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false
"strict": true,
"noUnusedLocals": true
},
"include": ["src/**/*.ts", "src/index.ts"]
}
48 changes: 48 additions & 0 deletions web/package-lock.json

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

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
},
"dependencies": {
"@hookform/resolvers": "^3.1.1",
"@tanstack/react-query": "^5.0.5",
"axios": "^1.4.0",
"date-fns": "^2.30.0",
"dotenv": "^16.3.1",
Expand Down
83 changes: 46 additions & 37 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
createBrowserRouter,
Route,
createRoutesFromElements,
RouterProvider,
} from 'react-router-dom';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { eventDetailsLoader, eventsLoader } from './Services/loaderFunctions';
//Layouts
import RootLayout from './Layout/RootLayout';
Expand All @@ -12,42 +7,56 @@ import LoginForm from './Components/LoginForm';
import EventList from './Components/EventList/EventList';
import EventDetails from './Components/EventDetails/EventDetails';
import NotFound from './Components/Error/NotFound';
import EventDetailsError from './Components/Error/EventDetailsError';
import EditEvent from './Components/EditEvent/EditEvent';
import RegistrationForm from './Components/RegistrationForm';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import DefaultErrorComponent from './Components/Error/DefaultErrorComponent';

const queryClient = new QueryClient();

const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
errorElement: <DefaultErrorComponent />,
children: [
{
path: 'login',
element: <LoginForm />,
},
{
path: 'register',
element: <RegistrationForm />,
},
{
path: 'edit/:id',
element: <EditEvent />,
loader: eventDetailsLoader(queryClient),
},
{
index: true,
element: <EventList />,
loader: eventsLoader(queryClient),
},
{
path: ':id',
element: <EventDetails />,
loader: eventDetailsLoader(queryClient),
},
{
path: '*',
element: <NotFound />,
},
],
},
]);

function App() {
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<RootLayout />}>
<Route
path="login"
element={<LoginForm />}
errorElement={<NotFound />}
/>
<Route
path="register"
element={<RegistrationForm />}
errorElement={<NotFound />}
/>
<Route
path="edit/:id"
element={<EditEvent />}
loader={eventDetailsLoader}
errorElement={<EventDetailsError />}
/>
<Route index element={<EventList />} loader={eventsLoader} />
<Route
path=":id"
element={<EventDetails />}
loader={eventDetailsLoader}
errorElement={<EventDetailsError />}
/>
<Route path="*" element={<NotFound />} />
</Route>,
),
return (
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
);
return <RouterProvider router={router} />;
}

export default App;
2 changes: 1 addition & 1 deletion web/src/Components/EditEvent/EventForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
EditCommunityEvent,
CommunityEventType,
} from '../../types';
import eventService from '../../Services/eventService';
import * as eventService from '../../Services/eventService';
import eventTypeService from '../../Services/eventTypeService';
import { useNavigate } from 'react-router-dom';
import { useEffect, useState } from 'react';
Expand Down
23 changes: 23 additions & 0 deletions web/src/Components/Error/DefaultErrorComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Link, Navigate, useRouteError } from 'react-router-dom';
import {
NotFoundError,
UnauthorizedError,
} from '../../Services/loaderFunctions';
import NotFound from './NotFound';

export default function DefaultErrorComponent() {
const error = useRouteError();
if (error instanceof UnauthorizedError) {
return <Navigate to="/login" />;
}
if (error instanceof NotFoundError) {
return <NotFound />;
}
return (
<main>
<h1>Oops!</h1>
<p>Something went wrong.</p>
<Link to="/">Back to home</Link>
</main>
);
}
Loading

0 comments on commit 63183a7

Please sign in to comment.