diff --git a/apps/backoffice/src/app/features/auth/components/LoginForm.tsx b/apps/backoffice/src/app/features/auth/components/LoginForm.tsx
index ebf09bd45..57e463101 100644
--- a/apps/backoffice/src/app/features/auth/components/LoginForm.tsx
+++ b/apps/backoffice/src/app/features/auth/components/LoginForm.tsx
@@ -6,11 +6,12 @@ import {
Title,
Paper,
Text,
+ Anchor,
} from '@mantine/core';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
-import { useNavigate } from 'react-router-dom';
+import { useNavigate, Link } from 'react-router-dom';
import { useLoginMutation } from '../api/auth-api';
import { useAuth } from '../hooks/useAuth';
import { notify } from '@ema-platform/ui';
@@ -72,8 +73,14 @@ export function LoginForm() {
Sign in
-
-
-
+
+
+ Don't have an account?{' '}
+
+ Sign up
+
+
+
+
);
}
diff --git a/apps/backoffice/src/app/features/auth/pages/SetPasswordPage.tsx b/apps/backoffice/src/app/features/auth/pages/SetPasswordPage.tsx
new file mode 100644
index 000000000..41e311be9
--- /dev/null
+++ b/apps/backoffice/src/app/features/auth/pages/SetPasswordPage.tsx
@@ -0,0 +1,137 @@
+import {
+ Paper,
+ TextInput,
+ PasswordInput,
+ Button,
+ Stack,
+ Title,
+ Text,
+} from '@mantine/core';
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { useNavigate, useLocation } from 'react-router-dom';
+import { useAppDispatch, useAppSelector } from '../../../store/hooks';
+import {
+ setPasswordStart,
+ setPasswordSuccess,
+ setPasswordFailure,
+} from '../store/set-password.slice';
+import { notify } from '@ema-platform/ui';
+
+const BASE_API_URL =
+ (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ??
+ 'http://localhost:3001/api';
+
+const schema = z
+ .object({
+ userId: z.string().min(1, 'User ID is required'),
+ email: z.string().email('Enter a valid email'),
+ verificationCode: z.string().min(1, 'Verification code is required'),
+ newPassword: z.string().min(6, 'Password must be at least 6 characters'),
+ confirmPassword: z.string().min(6, 'Confirm your password'),
+ })
+ .refine((data) => data.newPassword === data.confirmPassword, {
+ message: 'Passwords do not match',
+ path: ['confirmPassword'],
+ });
+
+type FormValues = z.infer;
+
+export function SetPasswordPage() {
+ const navigate = useNavigate();
+ const dispatch = useAppDispatch();
+ const location = useLocation();
+ const { loading } = useAppSelector((s) => s.setPassword);
+ const signupEmail = (location.state as { email?: string } | null)?.email ?? '';
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: zodResolver(schema),
+ defaultValues: { email: signupEmail },
+ });
+
+ const onSubmit = async (values: FormValues) => {
+ dispatch(setPasswordStart());
+ try {
+ const res = await fetch(`${BASE_API_URL}/auth/set-password`, {
+ method: 'PATCH',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ userId: values.userId,
+ email: values.email,
+ verificationCode: values.verificationCode,
+ newPassword: values.newPassword,
+ confirmPassword: values.confirmPassword,
+ }),
+ });
+
+ if (!res.ok) {
+ const errorData = await res.json().catch(() => null);
+ throw new Error(errorData?.message ?? 'Failed to set password');
+ }
+
+ dispatch(setPasswordSuccess());
+ notify.success('Password set successfully');
+ navigate('/dashboard');
+ } catch (err) {
+ const msg = err instanceof Error ? err.message : 'Something went wrong';
+ dispatch(setPasswordFailure(msg));
+ notify.error(msg);
+ }
+ };
+
+ return (
+
+
+
+ Set your password
+
+ A verification code has been sent to your email. Enter it below along
+ with your new password to complete registration.
+
+
+
+
+
+ );
+}
diff --git a/apps/backoffice/src/app/features/auth/pages/SignupPage.tsx b/apps/backoffice/src/app/features/auth/pages/SignupPage.tsx
new file mode 100644
index 000000000..05ce9eae0
--- /dev/null
+++ b/apps/backoffice/src/app/features/auth/pages/SignupPage.tsx
@@ -0,0 +1,153 @@
+import {
+ Paper,
+ TextInput,
+ Button,
+ Stack,
+ Title,
+ Text,
+ Anchor,
+} from '@mantine/core';
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { useNavigate, Link } from 'react-router-dom';
+import { useAppDispatch, useAppSelector } from '../../../store/hooks';
+import { signupStart, signupSuccess, signupFailure } from '../store/signup.slice';
+import { hydrateAuth } from '../store/auth.slice';
+import { authStorage } from '../utils/auth-storage';
+import { notify } from '@ema-platform/ui';
+
+const BASE_API_URL =
+ (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ??
+ 'http://localhost:3001/api';
+
+const schema = z.object({
+ email: z.string().email('Enter a valid email'),
+ username: z.string().min(3, 'Username must be at least 3 characters'),
+ phoneNumber: z.string().min(1, 'Phone number is required'),
+ userType: z.string().min(1, 'User type is required'),
+ name: z.string().min(1, 'Name is required'),
+});
+
+type FormValues = z.infer;
+
+interface SignupPayload {
+ email: string;
+ username: string;
+ phoneNumber: string;
+ userType: string;
+ name: {
+ am: string;
+ en: string;
+ };
+}
+
+export function SignupPage() {
+ const navigate = useNavigate();
+ const dispatch = useAppDispatch();
+ const { loading } = useAppSelector((s) => s.signup);
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: zodResolver(schema),
+ });
+
+ const onSubmit = async (values: FormValues) => {
+ dispatch(signupStart());
+ try {
+ const payload: SignupPayload = {
+ email: values.email,
+ username: values.username,
+ phoneNumber: values.phoneNumber,
+ userType: values.userType,
+ name: {
+ am: '',
+ en: values.name,
+ },
+ };
+
+ const res = await fetch(`${BASE_API_URL}/auth/signup`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload),
+ });
+
+ if (!res.ok) {
+ const errorData = await res.json().catch(() => null);
+ throw new Error(errorData?.message ?? 'Signup failed');
+ }
+
+ const data = (await res.json()) as { token: string; refreshToken: string };
+
+ authStorage.setToken(data.token);
+ authStorage.setRefreshToken(data.refreshToken);
+ dispatch(hydrateAuth());
+ dispatch(signupSuccess());
+
+ navigate('/set-password', { state: { email: values.email } });
+ } catch (err) {
+ const msg = err instanceof Error ? err.message : 'Something went wrong';
+ dispatch(signupFailure(msg));
+ notify.error(msg);
+ }
+ };
+
+ return (
+
+
+
+ Create an account
+
+ Fill in your details to get started
+
+
+
+
+ Already have an account?{' '}
+
+ Sign in
+
+
+
+
+ );
+}
diff --git a/apps/backoffice/src/app/features/auth/store/set-password.slice.ts b/apps/backoffice/src/app/features/auth/store/set-password.slice.ts
new file mode 100644
index 000000000..bdcf8d745
--- /dev/null
+++ b/apps/backoffice/src/app/features/auth/store/set-password.slice.ts
@@ -0,0 +1,42 @@
+import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
+
+interface SetPasswordState {
+ loading: boolean;
+ success: boolean;
+ error: string | null;
+}
+
+const initialState: SetPasswordState = {
+ loading: false,
+ success: false,
+ error: null,
+};
+
+const setPasswordSlice = createSlice({
+ name: 'setPassword',
+ initialState,
+ reducers: {
+ setPasswordStart(state) {
+ state.loading = true;
+ state.error = null;
+ state.success = false;
+ },
+ setPasswordSuccess(state) {
+ state.loading = false;
+ state.success = true;
+ },
+ setPasswordFailure(state, action: PayloadAction) {
+ state.loading = false;
+ state.error = action.payload;
+ },
+ resetSetPassword(state) {
+ state.loading = false;
+ state.success = false;
+ state.error = null;
+ },
+ },
+});
+
+export const { setPasswordStart, setPasswordSuccess, setPasswordFailure, resetSetPassword } =
+ setPasswordSlice.actions;
+export const setPasswordReducer = setPasswordSlice.reducer;
diff --git a/apps/backoffice/src/app/features/auth/store/signup.slice.ts b/apps/backoffice/src/app/features/auth/store/signup.slice.ts
new file mode 100644
index 000000000..92a5f4294
--- /dev/null
+++ b/apps/backoffice/src/app/features/auth/store/signup.slice.ts
@@ -0,0 +1,41 @@
+import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
+
+interface SignupState {
+ loading: boolean;
+ success: boolean;
+ error: string | null;
+}
+
+const initialState: SignupState = {
+ loading: false,
+ success: false,
+ error: null,
+};
+
+const signupSlice = createSlice({
+ name: 'signup',
+ initialState,
+ reducers: {
+ signupStart(state) {
+ state.loading = true;
+ state.error = null;
+ state.success = false;
+ },
+ signupSuccess(state) {
+ state.loading = false;
+ state.success = true;
+ },
+ signupFailure(state, action: PayloadAction) {
+ state.loading = false;
+ state.error = action.payload;
+ },
+ resetSignup(state) {
+ state.loading = false;
+ state.success = false;
+ state.error = null;
+ },
+ },
+});
+
+export const { signupStart, signupSuccess, signupFailure, resetSignup } = signupSlice.actions;
+export const signupReducer = signupSlice.reducer;
diff --git a/apps/backoffice/src/app/router/index.tsx b/apps/backoffice/src/app/router/index.tsx
index 797c57e57..44a27ae6e 100644
--- a/apps/backoffice/src/app/router/index.tsx
+++ b/apps/backoffice/src/app/router/index.tsx
@@ -3,6 +3,8 @@ import { ProtectedRoute } from './ProtectedRoute';
import { BackofficeLayout } from '../layouts/BackofficeLayout';
import { AuthLayout } from '../layouts/AuthLayout';
import { LoginPage } from '../features/auth/pages/LoginPage';
+import { SignupPage } from '../features/auth/pages/SignupPage';
+import { SetPasswordPage } from '../features/auth/pages/SetPasswordPage';
import { DashboardPage } from '../features/dashboard/pages/DashboardPage';
import { ItemPage } from '../features/item/pages/ItemPage';
@@ -22,7 +24,11 @@ const router = createBrowserRouter([
},
{
element: ,
- children: [{ path: '/login', element: }],
+ children: [
+ { path: '/login', element: },
+ { path: '/signup', element: },
+ { path: '/set-password', element: },
+ ],
},
{ path: '/404', element: Page not found
},
{ path: '*', element: },
diff --git a/apps/backoffice/src/app/store/index.ts b/apps/backoffice/src/app/store/index.ts
index bc34aa245..bed66a931 100644
--- a/apps/backoffice/src/app/store/index.ts
+++ b/apps/backoffice/src/app/store/index.ts
@@ -1,10 +1,14 @@
import { configureStore } from '@reduxjs/toolkit';
import { baseApi } from '@ema-platform/api';
import { authReducer } from '../features/auth/store/auth.slice';
+import { signupReducer } from '../features/auth/store/signup.slice';
+import { setPasswordReducer } from '../features/auth/store/set-password.slice';
export const store = configureStore({
reducer: {
auth: authReducer,
+ signup: signupReducer,
+ setPassword: setPasswordReducer,
[baseApi.reducerPath]: baseApi.reducer,
},
middleware: (getDefaultMiddleware) =>
diff --git a/apps/portal/src/app/features/auth/pages/LoginPage.tsx b/apps/portal/src/app/features/auth/pages/LoginPage.tsx
index 898639783..f0153f2ef 100644
--- a/apps/portal/src/app/features/auth/pages/LoginPage.tsx
+++ b/apps/portal/src/app/features/auth/pages/LoginPage.tsx
@@ -7,11 +7,13 @@ import {
Stack,
Title,
Center,
+ Text,
+ Anchor,
} from '@mantine/core';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
-import { useNavigate } from 'react-router-dom';
+import { useNavigate, Link } from 'react-router-dom';
import { useAuth } from '../hooks/useAuth';
import { notify } from '@ema-platform/ui';
@@ -82,6 +84,12 @@ export function LoginPage() {
+
+ Don't have an account?{' '}
+
+ Sign up
+
+
diff --git a/apps/portal/src/app/features/auth/pages/SetPasswordPage.tsx b/apps/portal/src/app/features/auth/pages/SetPasswordPage.tsx
new file mode 100644
index 000000000..eb2837420
--- /dev/null
+++ b/apps/portal/src/app/features/auth/pages/SetPasswordPage.tsx
@@ -0,0 +1,138 @@
+import {
+ Paper,
+ TextInput,
+ PasswordInput,
+ Button,
+ Stack,
+ Title,
+ Center,
+ Text,
+} from '@mantine/core';
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { useNavigate, useLocation } from 'react-router-dom';
+import { useAppDispatch, useAppSelector } from '../../../store/hooks';
+import {
+ setPasswordStart,
+ setPasswordSuccess,
+ setPasswordFailure,
+} from '../store/set-password.slice';
+import { notify } from '@ema-platform/ui';
+
+const BASE_API_URL =
+ (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ??
+ 'http://localhost:3001/api';
+
+const schema = z
+ .object({
+ userId: z.string().min(1, 'User ID is required'),
+ email: z.string().email('Enter a valid email'),
+ verificationCode: z.string().min(1, 'Verification code is required'),
+ newPassword: z.string().min(6, 'Password must be at least 6 characters'),
+ confirmPassword: z.string().min(6, 'Confirm your password'),
+ })
+ .refine((data) => data.newPassword === data.confirmPassword, {
+ message: 'Passwords do not match',
+ path: ['confirmPassword'],
+ });
+
+type FormValues = z.infer;
+
+export function SetPasswordPage() {
+ const navigate = useNavigate();
+ const dispatch = useAppDispatch();
+ const location = useLocation();
+ const { loading } = useAppSelector((s) => s.setPassword);
+ const signupEmail = (location.state as { email?: string } | null)?.email ?? '';
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: zodResolver(schema),
+ defaultValues: { email: signupEmail },
+ });
+
+ const onSubmit = async (values: FormValues) => {
+ dispatch(setPasswordStart());
+ try {
+ const res = await fetch(`${BASE_API_URL}/auth/set-password`, {
+ method: 'PATCH',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ userId: values.userId,
+ email: values.email,
+ verificationCode: values.verificationCode,
+ newPassword: values.newPassword,
+ confirmPassword: values.confirmPassword,
+ }),
+ });
+
+ if (!res.ok) {
+ const errorData = await res.json().catch(() => null);
+ throw new Error(errorData?.message ?? 'Failed to set password');
+ }
+
+ dispatch(setPasswordSuccess());
+ notify.success('Password set successfully');
+ navigate('/dashboard');
+ } catch (err) {
+ const msg = err instanceof Error ? err.message : 'Something went wrong';
+ dispatch(setPasswordFailure(msg));
+ notify.error(msg);
+ }
+ };
+
+ return (
+
+
+
+ Set your password
+
+ A verification code has been sent to your email. Enter it below along
+ with your new password to complete registration.
+
+
+
+
+
+ );
+}
diff --git a/apps/portal/src/app/features/auth/pages/SignupPage.tsx b/apps/portal/src/app/features/auth/pages/SignupPage.tsx
new file mode 100644
index 000000000..2a277e457
--- /dev/null
+++ b/apps/portal/src/app/features/auth/pages/SignupPage.tsx
@@ -0,0 +1,151 @@
+import {
+ Paper,
+ TextInput,
+ Button,
+ Stack,
+ Title,
+ Center,
+ Text,
+ Anchor,
+} from '@mantine/core';
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { useNavigate, Link } from 'react-router-dom';
+import { useAppDispatch, useAppSelector } from '../../../store/hooks';
+import { signupStart, signupSuccess, signupFailure } from '../store/signup.slice';
+import { hydrateAuth } from '../store/auth.slice';
+import { authStorage } from '../utils/auth-storage';
+import { notify } from '@ema-platform/ui';
+
+const BASE_API_URL =
+ (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ??
+ 'http://localhost:3001/api';
+
+const schema = z.object({
+ email: z.string().email('Enter a valid email'),
+ username: z.string().min(3, 'Username must be at least 3 characters'),
+ phoneNumber: z.string().min(1, 'Phone number is required'),
+ userType: z.string().min(1, 'User type is required'),
+ name: z.string().min(1, 'Name is required'),
+});
+
+type FormValues = z.infer;
+
+interface SignupPayload {
+ email: string;
+ username: string;
+ phoneNumber: string;
+ userType: string;
+ name: {
+ am: string;
+ en: string;
+ };
+}
+
+export function SignupPage() {
+ const navigate = useNavigate();
+ const dispatch = useAppDispatch();
+ const { loading } = useAppSelector((s) => s.signup);
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: zodResolver(schema),
+ });
+
+ const onSubmit = async (values: FormValues) => {
+ dispatch(signupStart());
+ try {
+ const payload: SignupPayload = {
+ email: values.email,
+ username: values.username,
+ phoneNumber: values.phoneNumber,
+ userType: values.userType,
+ name: {
+ am: '',
+ en: values.name,
+ },
+ };
+
+ const res = await fetch(`${BASE_API_URL}/auth/signup`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload),
+ });
+
+ if (!res.ok) {
+ const errorData = await res.json().catch(() => null);
+ throw new Error(errorData?.message ?? 'Signup failed');
+ }
+
+ const data = (await res.json()) as { token: string; refreshToken: string };
+
+ authStorage.setToken(data.token);
+ authStorage.setRefreshToken(data.refreshToken);
+ dispatch(hydrateAuth());
+ dispatch(signupSuccess());
+
+ navigate('/set-password', { state: { email: values.email } });
+ } catch (err) {
+ const msg = err instanceof Error ? err.message : 'Something went wrong';
+ dispatch(signupFailure(msg));
+ notify.error(msg);
+ }
+ };
+
+ return (
+
+
+
+ Create an account
+
+
+ Already have an account?{' '}
+
+ Sign in
+
+
+
+
+
+ );
+}
diff --git a/apps/portal/src/app/features/auth/store/set-password.slice.ts b/apps/portal/src/app/features/auth/store/set-password.slice.ts
new file mode 100644
index 000000000..bdcf8d745
--- /dev/null
+++ b/apps/portal/src/app/features/auth/store/set-password.slice.ts
@@ -0,0 +1,42 @@
+import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
+
+interface SetPasswordState {
+ loading: boolean;
+ success: boolean;
+ error: string | null;
+}
+
+const initialState: SetPasswordState = {
+ loading: false,
+ success: false,
+ error: null,
+};
+
+const setPasswordSlice = createSlice({
+ name: 'setPassword',
+ initialState,
+ reducers: {
+ setPasswordStart(state) {
+ state.loading = true;
+ state.error = null;
+ state.success = false;
+ },
+ setPasswordSuccess(state) {
+ state.loading = false;
+ state.success = true;
+ },
+ setPasswordFailure(state, action: PayloadAction) {
+ state.loading = false;
+ state.error = action.payload;
+ },
+ resetSetPassword(state) {
+ state.loading = false;
+ state.success = false;
+ state.error = null;
+ },
+ },
+});
+
+export const { setPasswordStart, setPasswordSuccess, setPasswordFailure, resetSetPassword } =
+ setPasswordSlice.actions;
+export const setPasswordReducer = setPasswordSlice.reducer;
diff --git a/apps/portal/src/app/features/auth/store/signup.slice.ts b/apps/portal/src/app/features/auth/store/signup.slice.ts
new file mode 100644
index 000000000..92a5f4294
--- /dev/null
+++ b/apps/portal/src/app/features/auth/store/signup.slice.ts
@@ -0,0 +1,41 @@
+import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
+
+interface SignupState {
+ loading: boolean;
+ success: boolean;
+ error: string | null;
+}
+
+const initialState: SignupState = {
+ loading: false,
+ success: false,
+ error: null,
+};
+
+const signupSlice = createSlice({
+ name: 'signup',
+ initialState,
+ reducers: {
+ signupStart(state) {
+ state.loading = true;
+ state.error = null;
+ state.success = false;
+ },
+ signupSuccess(state) {
+ state.loading = false;
+ state.success = true;
+ },
+ signupFailure(state, action: PayloadAction) {
+ state.loading = false;
+ state.error = action.payload;
+ },
+ resetSignup(state) {
+ state.loading = false;
+ state.success = false;
+ state.error = null;
+ },
+ },
+});
+
+export const { signupStart, signupSuccess, signupFailure, resetSignup } = signupSlice.actions;
+export const signupReducer = signupSlice.reducer;
diff --git a/apps/portal/src/app/router.tsx b/apps/portal/src/app/router.tsx
index 2e6e41493..52dd0f96e 100644
--- a/apps/portal/src/app/router.tsx
+++ b/apps/portal/src/app/router.tsx
@@ -2,6 +2,8 @@ import { createBrowserRouter, RouterProvider, Navigate } from 'react-router-dom'
import type { ReactNode } from 'react';
import { PortalLayout } from './layouts/PortalLayout';
import { LoginPage } from './features/auth/pages/LoginPage';
+import { SignupPage } from './features/auth/pages/SignupPage';
+import { SetPasswordPage } from './features/auth/pages/SetPasswordPage';
import { DashboardPage } from './features/dashboard/pages/DashboardPage';
function getToken(): string | null {
@@ -15,6 +17,8 @@ function ProtectedRoute({ children }: { children: ReactNode }) {
const router = createBrowserRouter([
{ path: '/login', element: },
+ { path: '/signup', element: },
+ { path: '/set-password', element: },
{
element: ,
children: [
diff --git a/apps/portal/src/app/store/index.ts b/apps/portal/src/app/store/index.ts
index bc34aa245..bed66a931 100644
--- a/apps/portal/src/app/store/index.ts
+++ b/apps/portal/src/app/store/index.ts
@@ -1,10 +1,14 @@
import { configureStore } from '@reduxjs/toolkit';
import { baseApi } from '@ema-platform/api';
import { authReducer } from '../features/auth/store/auth.slice';
+import { signupReducer } from '../features/auth/store/signup.slice';
+import { setPasswordReducer } from '../features/auth/store/set-password.slice';
export const store = configureStore({
reducer: {
auth: authReducer,
+ signup: signupReducer,
+ setPassword: setPasswordReducer,
[baseApi.reducerPath]: baseApi.reducer,
},
middleware: (getDefaultMiddleware) =>
diff --git a/libs/api/src/lib/base-api/index.ts b/libs/api/src/lib/base-api/index.ts
index d22ba6101..6070cff60 100644
--- a/libs/api/src/lib/base-api/index.ts
+++ b/libs/api/src/lib/base-api/index.ts
@@ -3,7 +3,7 @@ import { resolveSessionContext } from '../session';
const BASE_API_URL =
(import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ??
- 'http://localhost:3001';
+ 'http://localhost:3001/api';
export const baseApi = createApi({
reducerPath: 'baseApi',