Skip to content

Commit bb34c54

Browse files
committed
Update frontend to use new gateway
1 parent a17a5c2 commit bb34c54

File tree

13 files changed

+93
-56
lines changed

13 files changed

+93
-56
lines changed

docker-compose.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ services:
44
context: ./frontend
55
args:
66
- BASE_URI=$BASE_URI
7-
- USER_SVC_PORT=$USER_SVC_PORT
8-
- QUESTION_SVC_PORT=$QUESTION_SVC_PORT
9-
- MATCHING_SVC_PORT=$MATCHING_SVC_PORT
10-
depends_on:
11-
- question-service
12-
- user-service
7+
- API_GATEWAY_PORT=$API_GATEWAY_PORT
138
environment:
149
- PORT=$FRONTEND_PORT
1510

frontend/Dockerfile

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
# Base stage
22
FROM node:20-alpine AS base
33
ARG BASE_URI \
4-
USER_SVC_PORT \
5-
QUESTION_SVC_PORT \
6-
MATCHING_SVC_PORT
4+
API_GATEWAY_PORT
75
WORKDIR /app
86
COPY package.json .
97
COPY yarn.lock .
108
RUN yarn install --frozen-lockfile
119
ENV NEXT_PUBLIC_BASE_URI=$BASE_URI \
12-
NEXT_PUBLIC_USER_SVC_PORT=$USER_SVC_PORT \
13-
NEXT_PUBLIC_QUESTION_SVC_PORT=$QUESTION_SVC_PORT \
14-
NEXT_PUBLIC_MATCHING_SVC_PORT=$MATCHING_SVC_PORT
10+
NEXT_PUBLIC_API_GATEWAY_PORT=$API_GATEWAY_PORT
1511

1612
# Production build stage
1713
FROM base AS build

frontend/app/auth/auth-context.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { userServiceUri } from "@/lib/api-uri";
3+
import { AuthType, userServiceUri } from "@/lib/api-uri";
44
import { User, UserSchema } from "@/lib/schemas/user-schema";
55
import { useRouter } from "next/navigation";
66
import {
@@ -33,12 +33,15 @@ const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
3333
// Login using locally stored JWT token
3434
useEffect(() => {
3535
if (token) {
36-
fetch(`${userServiceUri(window.location.hostname)}/auth/verify-token`, {
37-
method: "GET",
38-
headers: {
39-
Authorization: `Bearer ${token}`,
40-
},
41-
})
36+
fetch(
37+
`${userServiceUri(window.location.hostname, AuthType.Public)}/auth/verify-token`,
38+
{
39+
method: "GET",
40+
headers: {
41+
Authorization: `Bearer ${token}`,
42+
},
43+
}
44+
)
4245
.then((res) => {
4346
res.json().then((result) => {
4447
setUser(result.data);
@@ -53,7 +56,7 @@ const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
5356
// Login using email and password
5457
const login = async (email: string, password: string): Promise<User> => {
5558
const response = await fetch(
56-
`${userServiceUri(window.location.hostname)}/auth/login`,
59+
`${userServiceUri(window.location.hostname, AuthType.Public)}/auth/login`,
5760
{
5861
method: "POST",
5962
headers: {

frontend/components/admin-user-management/admin-user-management.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import LoadingScreen from "@/components/common/loading-screen";
1616
import AdminEditUserModal from "@/components/admin-user-management/admin-edit-user-modal";
1717
import { PencilIcon, Trash2Icon } from "lucide-react";
1818
import { User, UserArraySchema } from "@/lib/schemas/user-schema";
19-
import { userServiceUri } from "@/lib/api-uri";
19+
import { AuthType, userServiceUri } from "@/lib/api-uri";
2020

2121
const fetcher = async (url: string): Promise<User[]> => {
2222
const token = localStorage.getItem("jwtToken");
@@ -44,7 +44,7 @@ export default function AdminUserManagement() {
4444
const auth = useAuth();
4545

4646
const { data, isLoading, mutate } = useSWR(
47-
`${userServiceUri(window.location.hostname)}/users`,
47+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users`,
4848
fetcher
4949
);
5050

@@ -69,7 +69,7 @@ export default function AdminUserManagement() {
6969
}
7070

7171
const response = await fetch(
72-
`${userServiceUri(window.location.hostname)}/users/${userId}`,
72+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/${userId}`,
7373
{
7474
method: "DELETE",
7575
headers: {

frontend/components/forget-password.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Label } from "@/components/ui/label";
1515
import { Button } from "@/components/ui/button";
1616
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
1717
import { AlertCircle } from "lucide-react";
18-
import { userServiceUri } from "@/lib/api-uri";
18+
import { AuthType, userServiceUri } from "@/lib/api-uri";
1919

2020
const ForgetPassword: React.FC = () => {
2121
const [email, setEmail] = useState("");
@@ -36,7 +36,7 @@ const ForgetPassword: React.FC = () => {
3636

3737
try {
3838
const response = await fetch(
39-
`${userServiceUri(window.location.hostname)}/users/forget-password`,
39+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/forget-password`,
4040
{
4141
method: "POST",
4242
headers: {

frontend/components/questions/questions-listing.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
} from "@/lib/schemas/question-schema";
1919
import QuestionFormModal from "./question-form-modal";
2020
import { updateQuestion } from "@/lib/update-question";
21-
import { questionServiceUri } from "@/lib/api-uri";
21+
import { AuthType, questionServiceUri } from "@/lib/api-uri";
2222

2323
const fetcher = async (url: string): Promise<Question[]> => {
2424
const token = localStorage.getItem("jwtToken");
@@ -56,7 +56,7 @@ export default function QuestionListing() {
5656
const [search, setSearch] = useState(searchParams.get("search") || "");
5757

5858
const { data, isLoading, mutate } = useSWR(
59-
`${questionServiceUri(window.location.hostname)}/questions?category=${encodeURIComponent(category)}&complexity=${encodeURIComponent(complexity)}&search=${encodeURIComponent(search)}`,
59+
`${questionServiceUri(window.location.hostname, AuthType.Public)}/questions?category=${encodeURIComponent(category)}&complexity=${encodeURIComponent(complexity)}&search=${encodeURIComponent(search)}`,
6060
fetcher,
6161
{
6262
keepPreviousData: true,
@@ -144,13 +144,16 @@ export default function QuestionListing() {
144144
const handleBatchUpload = async (questions: CreateQuestion[]) => {
145145
try {
146146
const token = localStorage.getItem("jwtToken");
147+
if (!token) {
148+
throw new Error("No authentication token found");
149+
}
147150
const response = await fetch(
148-
`${questionServiceUri(window.location.hostname)}/questions/batch-upload`,
151+
`${questionServiceUri(window.location.hostname, AuthType.Admin)}/questions/batch-upload`,
149152
{
150153
method: "POST",
151154
headers: {
152-
"Content-Type": "application/json",
153155
Authorization: `Bearer ${token}`,
156+
"Content-Type": "application/json",
154157
},
155158
body: JSON.stringify(questions),
156159
}
@@ -188,11 +191,20 @@ export default function QuestionListing() {
188191
const handleDeleteQuestion = async () => {
189192
if (!selectedQuestion) return;
190193

194+
const token = localStorage.getItem("jwtToken");
195+
if (!token) {
196+
throw new Error("No authentication token found");
197+
}
198+
191199
try {
192200
const response = await fetch(
193-
`${questionServiceUri(window.location.hostname)}/questions/${selectedQuestion.id}`,
201+
`${questionServiceUri(window.location.hostname, AuthType.Admin)}/questions/${selectedQuestion.id}`,
194202
{
195203
method: "DELETE",
204+
headers: {
205+
Authorization: `Bearer ${token}`,
206+
"Content-Type": "application/json",
207+
},
196208
}
197209
);
198210

@@ -225,7 +237,12 @@ export default function QuestionListing() {
225237
};
226238

227239
const handleEdit = async (question: Question) => {
228-
const response = await updateQuestion(question);
240+
const token = localStorage.getItem("jwtToken");
241+
if (!token) {
242+
throw new Error("No authentication token found");
243+
}
244+
245+
const response = await updateQuestion(token, question);
229246
if (!response.ok) {
230247
toast({
231248
title: "Unknown Error",
@@ -263,11 +280,17 @@ export default function QuestionListing() {
263280

264281
const handleCreate = async (newQuestion: Question) => {
265282
try {
283+
const token = localStorage.getItem("jwtToken");
284+
if (!token) {
285+
throw new Error("No authentication token found");
286+
}
287+
266288
const response = await fetch(
267-
`${questionServiceUri(window.location.hostname)}/questions`,
289+
`${questionServiceUri(window.location.hostname, AuthType.Admin)}/questions`,
268290
{
269291
method: "POST",
270292
headers: {
293+
Authorization: `Bearer ${token}`,
271294
"Content-Type": "application/json",
272295
},
273296
body: JSON.stringify({

frontend/components/user-settings/user-settings.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import LoadingScreen from "@/components/common/loading-screen";
2424
import { useAuth } from "@/app/auth/auth-context";
2525
import { cn } from "@/lib/utils";
2626
import { User, UserSchema } from "@/lib/schemas/user-schema";
27-
import { userServiceUri } from "@/lib/api-uri";
27+
import { AuthType, userServiceUri } from "@/lib/api-uri";
2828

2929
const fetcher = async (url: string): Promise<User> => {
3030
// Retrieve the JWT token from localStorage
@@ -55,7 +55,7 @@ export default function UserSettings({ userId }: { userId: string }) {
5555
const fileInputRef = useRef<HTMLInputElement>(null);
5656

5757
const { data, error, isLoading, mutate } = useSWR(
58-
`${userServiceUri(window.location.hostname)}/users/${userId}`,
58+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/${userId}`,
5959
fetcher
6060
);
6161
const [user, setUser] = useState<User | null>(null);
@@ -141,7 +141,7 @@ export default function UserSettings({ userId }: { userId: string }) {
141141

142142
try {
143143
const response = await fetch(
144-
`${userServiceUri(window.location.hostname)}/users/${userId}`,
144+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/${userId}`,
145145
{
146146
method: "PATCH",
147147
headers: {
@@ -182,7 +182,7 @@ export default function UserSettings({ userId }: { userId: string }) {
182182

183183
try {
184184
const response = await fetch(
185-
`${userServiceUri(window.location.hostname)}/users/${userId}`,
185+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/${userId}`,
186186
{
187187
method: "DELETE",
188188
headers: {
@@ -244,7 +244,7 @@ export default function UserSettings({ userId }: { userId: string }) {
244244

245245
try {
246246
const response = await fetch(
247-
`${userServiceUri(window.location.hostname)}/users/${userId}/change-password`,
247+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/${userId}/change-password`,
248248
{
249249
method: "PATCH",
250250
headers: {

frontend/lib/api-uri.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
1-
const constructUri = (baseUri: string, port: string | undefined) =>
2-
`http://${process.env.NEXT_PUBLIC_BASE_URI || baseUri}:${port}`;
1+
export enum AuthType {
2+
Public = "public",
3+
Private = "private",
4+
Owner = "owner",
5+
Admin = "admin",
6+
}
37

4-
export const userServiceUri: (baseUri: string) => string = (baseUri) =>
5-
constructUri(baseUri, process.env.NEXT_PUBLIC_USER_SVC_PORT);
6-
export const questionServiceUri: (baseUri: string) => string = (baseUri) =>
7-
constructUri(baseUri, process.env.NEXT_PUBLIC_QUESTION_SVC_PORT);
8-
export const matchingServiceUri: (baseUri: string) => string = (baseUri) =>
9-
constructUri(baseUri, process.env.NEXT_PUBLIC_MATCHING_SVC_PORT);
8+
const constructUri = (
9+
baseUri: string,
10+
authType: AuthType,
11+
serviceName: string
12+
) =>
13+
`http://${process.env.NEXT_PUBLIC_BASE_URI || baseUri}:${process.env.NEXT_PUBLIC_API_GATEWAY_PORT}/${authType}/${serviceName}`;
14+
15+
export const userServiceUri: (baseUri: string, authType: AuthType) => string = (
16+
baseUri,
17+
authType
18+
) => constructUri(baseUri, authType, "user-service");
19+
export const questionServiceUri: (
20+
baseUri: string,
21+
authType: AuthType
22+
) => string = (baseUri, authType) =>
23+
constructUri(baseUri, authType, "question-service");
24+
export const matchingServiceUri: (
25+
baseUri: string,
26+
authType: AuthType
27+
) => string = (baseUri, authType) =>
28+
constructUri(baseUri, authType, "matching-service");

frontend/lib/reset-password.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { userServiceUri } from "@/lib/api-uri";
1+
import { AuthType, userServiceUri } from "@/lib/api-uri";
22

33
export const resetPassword = async (token: string, password: string) => {
44
const response = await fetch(
5-
`${userServiceUri(window.location.hostname)}/users/reset-password`,
5+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users/reset-password`,
66
{
77
method: "POST",
88
headers: {

frontend/lib/signup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { userServiceUri } from "@/lib/api-uri";
1+
import { AuthType, userServiceUri } from "@/lib/api-uri";
22

33
export const signUp = async (
44
username: string,
55
email: string,
66
password: string
77
) => {
88
const response = await fetch(
9-
`${userServiceUri(window.location.hostname)}/users`,
9+
`${userServiceUri(window.location.hostname, AuthType.Public)}/users`,
1010
{
1111
method: "POST",
1212
headers: {

0 commit comments

Comments
 (0)