diff --git a/backend/src/routes/auth.js b/backend/src/routes/auth.js
index d6f29e8..addaaa4 100644
--- a/backend/src/routes/auth.js
+++ b/backend/src/routes/auth.js
@@ -62,6 +62,35 @@ router.post('/signin/local', wrapAsync(async (req, res) => {
res.status(200).send(payload);
}));
+/**
+ * @swagger
+ * /api/auth/signin/code:
+ * post:
+ * tags: [Auth]
+ * summary: Logs user into the system using access code
+ * description: Logs user into the system using access code
+ * requestBody:
+ * description: Set valid access code
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - code
+ * properties:
+ * code:
+ * type: string
+ * responses:
+ * 200:
+ * description: Successful login
+ * 400:
+ * description: Invalid code supplied
+ */
+router.post('/signin/code', wrapAsync(async (req, res) => {
+ const payload = await AuthService.signinWithCode(req.body.code);
+ res.status(200).send(payload);
+}));
+
/**
* @swagger
* /api/auth/me:
@@ -204,4 +233,4 @@ function socialRedirect(res, state, token, config) {
res.redirect(config.uiUrl + "/login?token=" + token);
}
-module.exports = router;
+module.exports = router;
\ No newline at end of file
diff --git a/backend/src/services/auth.js b/backend/src/services/auth.js
index 2862da4..6b348e4 100644
--- a/backend/src/services/auth.js
+++ b/backend/src/services/auth.js
@@ -1,4 +1,5 @@
const UsersDBApi = require('../db/api/users');
+const Access_codesDBApi = require('../db/api/access_codes');
const ValidationError = require('./notifications/errors/validation');
const ForbiddenError = require('./notifications/errors/forbidden');
const bcrypt = require('bcrypt');
@@ -8,6 +9,7 @@ const PasswordResetEmail = require('./email/list/passwordReset');
const EmailSender = require('./email');
const config = require('../config');
const helpers = require('../helpers');
+const db = require('../db/models');
class Auth {
static async signup(email, password, options = {}, host) {
@@ -18,6 +20,8 @@ class Auth {
config.bcrypt.saltRounds,
);
+ let currentUser;
+
if (user) {
if (user.authenticationUid) {
throw new ValidationError(
@@ -37,44 +41,40 @@ class Auth {
options,
);
- if (EmailSender.isConfigured) {
- await this.sendEmailAddressVerificationEmail(
- user.email,
- host,
- );
- }
-
- const data = {
- user: {
- id: user.id,
- email: user.email
- }
- };
-
- return helpers.jwtSign(data);
+ currentUser = user;
+ } else {
+ currentUser = await UsersDBApi.createFromAuth(
+ {
+ firstName: email.split('@')[0],
+ password: hashedPassword,
+ email: email,
+ },
+ options,
+ );
}
- const newUser = await UsersDBApi.createFromAuth(
- {
- firstName: email.split('@')[0],
- password: hashedPassword,
- email: email,
-
- },
- options,
- );
+ // Generate Access Code
+ const code = Math.random().toString(36).substring(2, 8).toUpperCase();
+ await Access_codesDBApi.create({
+ code,
+ status: 'active',
+ user: currentUser.id,
+ max_uses: 1000,
+ uses_count: 0
+ }, options);
if (EmailSender.isConfigured) {
await this.sendEmailAddressVerificationEmail(
- newUser.email,
+ currentUser.email,
host,
);
}
const data = {
user: {
- id: newUser.id,
- email: newUser.email
+ id: currentUser.id,
+ email: currentUser.email,
+ accessCode: code // Return the code so the user knows it
}
};
@@ -133,6 +133,35 @@ class Auth {
return helpers.jwtSign(data);
}
+ static async signinWithCode(code) {
+ const accessCode = await Access_codesDBApi.findBy({ code, status: 'active' });
+
+ if (!accessCode || !accessCode.user) {
+ throw new ValidationError('auth.invalidCode');
+ }
+
+ const user = await UsersDBApi.findBy({ id: accessCode.user.id });
+
+ if (!user || user.disabled) {
+ throw new ValidationError('auth.userDisabled');
+ }
+
+ // Update uses count
+ await Access_codesDBApi.update(accessCode.id, {
+ uses_count: (accessCode.uses_count || 0) + 1,
+ used_at: new Date()
+ }, { currentUser: user });
+
+ const data = {
+ user: {
+ id: user.id,
+ email: user.email
+ }
+ };
+
+ return helpers.jwtSign(data);
+ }
+
static async sendEmailAddressVerificationEmail(
email,
host,
@@ -309,4 +338,4 @@ class Auth {
}
}
-module.exports = Auth;
+module.exports = Auth;
\ No newline at end of file
diff --git a/frontend/src/components/NavBarItem.tsx b/frontend/src/components/NavBarItem.tsx
index eb155e3..1986306 100644
--- a/frontend/src/components/NavBarItem.tsx
+++ b/frontend/src/components/NavBarItem.tsx
@@ -1,6 +1,5 @@
-import React, {useEffect, useRef} from 'react'
+import React, {useEffect, useRef, useState} from 'react'
import Link from 'next/link'
-import { useState } from 'react'
import { mdiChevronUp, mdiChevronDown } from '@mdi/js'
import BaseDivider from './BaseDivider'
import BaseIcon from './BaseIcon'
@@ -129,4 +128,4 @@ export default function NavBarItem({ item }: Props) {
}
return
{NavBarItemComponentContents}
-}
+}
\ No newline at end of file
diff --git a/frontend/src/layouts/Authenticated.tsx b/frontend/src/layouts/Authenticated.tsx
index 1b9907d..26c3572 100644
--- a/frontend/src/layouts/Authenticated.tsx
+++ b/frontend/src/layouts/Authenticated.tsx
@@ -1,5 +1,4 @@
-import React, { ReactNode, useEffect } from 'react'
-import { useState } from 'react'
+import React, { ReactNode, useEffect, useState } from 'react'
import jwt from 'jsonwebtoken';
import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js'
import menuAside from '../menuAside'
@@ -126,4 +125,4 @@ export default function LayoutAuthenticated({
)
-}
+}
\ No newline at end of file
diff --git a/frontend/src/menuAside.ts b/frontend/src/menuAside.ts
index 126ebfa..12ee19d 100644
--- a/frontend/src/menuAside.ts
+++ b/frontend/src/menuAside.ts
@@ -7,6 +7,11 @@ const menuAside: MenuAsideItem[] = [
icon: icon.mdiViewDashboardOutline,
label: 'Dashboard',
},
+ {
+ href: '/studio',
+ icon: icon.mdiMusic,
+ label: 'Musical Studio',
+ },
{
href: '/users/users-list',
@@ -184,4 +189,4 @@ const menuAside: MenuAsideItem[] = [
},
]
-export default menuAside
+export default menuAside
\ No newline at end of file
diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx
index acbd0b8..e886ab1 100644
--- a/frontend/src/pages/index.tsx
+++ b/frontend/src/pages/index.tsx
@@ -1,166 +1,112 @@
-
-import React, { useEffect, useState } from 'react';
-import type { ReactElement } from 'react';
+import { ReactElement } from 'react';
import Head from 'next/head';
import Link from 'next/link';
-import BaseButton from '../components/BaseButton';
-import CardBox from '../components/CardBox';
-import SectionFullScreen from '../components/SectionFullScreen';
import LayoutGuest from '../layouts/Guest';
-import BaseDivider from '../components/BaseDivider';
-import BaseButtons from '../components/BaseButtons';
+import SectionFullScreen from '../components/SectionFullScreen';
+import { mdiMusic, mdiMicrophone, mdiPiano, mdiChartTimelineVariant } from '@mdi/js';
+import BaseIcon from '../components/BaseIcon';
import { getPageTitle } from '../config';
-import { useAppSelector } from '../stores/hooks';
-import CardBoxComponentTitle from "../components/CardBoxComponentTitle";
-import { getPexelsImage, getPexelsVideo } from '../helpers/pexels';
-
-
-export default function Starter() {
- const [illustrationImage, setIllustrationImage] = useState({
- src: undefined,
- photographer: undefined,
- photographer_url: undefined,
- })
- const [illustrationVideo, setIllustrationVideo] = useState({video_files: []})
- const [contentType, setContentType] = useState('image');
- const [contentPosition, setContentPosition] = useState('right');
- const textColor = useAppSelector((state) => state.style.linkColor);
-
- const title = 'Studio Musical Web'
-
- // Fetch Pexels image/video
- useEffect(() => {
- async function fetchData() {
- const image = await getPexelsImage();
- const video = await getPexelsVideo();
- setIllustrationImage(image);
- setIllustrationVideo(video);
- }
- fetchData();
- }, []);
-
- const imageBlock = (image) => (
-
- );
-
- const videoBlock = (video) => {
- if (video?.video_files?.length > 0) {
- return (
-
-
-
-
)
- }
- };
+export default function Home() {
+ const title = "AI Music Studio";
+
return (
-
+ <>
-
{getPageTitle('Starter Page')}
+
{getPageTitle('Home')}
-
-
- {contentType === 'image' && contentPosition !== 'background'
- ? imageBlock(illustrationImage)
- : null}
- {contentType === 'video' && contentPosition !== 'background'
- ? videoBlock(illustrationVideo)
- : null}
-
-
-
-
-
-
This is a React.js/Node.js app generated by the Flatlogic Web App Generator
-
For guides and documentation please check
- your local README.md and the Flatlogic documentation
+
+ {/* Navigation */}
+
+
+ {/* Hero Section */}
+
+
+
+
+
+ AI-Powered Music Composition
-
-
-
+
+ CREATE YOUR SYMPHONY IN SECONDS
+
+
+ From Sertanejo to Hip-Hop. Professional instruments, intelligent beats, and AI lyrics generator — all with just your access code.
+
+
+
+ Launch Studio
+
+
+ Enter with Code
+
+
+
+
-
-
+ {/* Features Section */}
+
+
+
+
+
+
AI Lyrics Engine
+
Input an idea, choose a style, and watch as our AI crafts a complete song structure with verses, chorus, and bridge.
+
+
+
+
World Instruments
+
Piano, Guitar, Accordion, Flute — access every instrument in the world with high-fidelity studio samples.
+
+
+
+
Beat Configurator
+
Customize rhythms, BPM, and swing. Perfect for any style from Sertanejo Raiz to Modern Hip-Hop.
+
+
+
-
-
-
-
© 2026 {title}. All rights reserved
-
- Privacy Policy
-
-
-
+ {/* Call to Action */}
+
+
+
+
Your music journey starts with one code.
+
Join thousands of creators building the future of sound.
+
+ Get Started Now
+
+
+
+
+ {/* Footer */}
+
+
+ >
);
}
-Starter.getLayout = function getLayout(page: ReactElement) {
+Home.getLayout = function getLayout(page: ReactElement) {
return
{page};
};
-
diff --git a/frontend/src/pages/login.tsx b/frontend/src/pages/login.tsx
index 8df0ac1..658910c 100644
--- a/frontend/src/pages/login.tsx
+++ b/frontend/src/pages/login.tsx
@@ -1,12 +1,10 @@
-
-
import React, { useEffect, useState } from 'react';
import type { ReactElement } from 'react';
import Head from 'next/head';
import BaseButton from '../components/BaseButton';
import CardBox from '../components/CardBox';
import BaseIcon from "../components/BaseIcon";
-import { mdiInformation, mdiEye, mdiEyeOff } from '@mdi/js';
+import { mdiInformation, mdiEye, mdiEyeOff, mdiKey, mdiEmail } from '@mdi/js';
import SectionFullScreen from '../components/SectionFullScreen';
import LayoutGuest from '../layouts/Guest';
import { Field, Form, Formik } from 'formik';
@@ -16,7 +14,7 @@ import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { useRouter } from 'next/router';
import { getPageTitle } from '../config';
-import { findMe, loginUser, resetAction } from '../stores/authSlice';
+import { findMe, loginUser, loginWithCode, resetAction } from '../stores/authSlice';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import Link from 'next/link';
import {toast, ToastContainer} from "react-toastify";
@@ -28,13 +26,14 @@ export default function Login() {
const textColor = useAppSelector((state) => state.style.linkColor);
const iconsColor = useAppSelector((state) => state.style.iconsColor);
const notify = (type, msg) => toast(msg, { type });
+ const [loginMethod, setLoginMethod] = useState<'email' | 'code'>('code');
const [ illustrationImage, setIllustrationImage ] = useState({
src: undefined,
photographer: undefined,
photographer_url: undefined,
})
const [ illustrationVideo, setIllustrationVideo ] = useState({video_files: []})
- const [contentType, setContentType] = useState('image');
+ const [contentType, setContentType] = useState('video');
const [contentPosition, setContentPosition] = useState('right');
const [showPassword, setShowPassword] = useState(false);
const { currentUser, isFetching, errorMessage, token, notify:notifyState } = useAppSelector(
@@ -44,7 +43,7 @@ export default function Login() {
password: '8e470127',
remember: true })
- const title = 'Studio Musical Web'
+ const title = 'AI Music Studio'
// Fetch Pexels image/video
useEffect( () => {
@@ -88,8 +87,12 @@ export default function Login() {
};
const handleSubmit = async (value) => {
- const {remember, ...rest} = value
- await dispatch(loginUser(rest));
+ if (loginMethod === 'email') {
+ const {remember, ...rest} = value
+ await dispatch(loginUser(rest));
+ } else {
+ await dispatch(loginWithCode({ code: value.code }));
+ }
};
const setLogin = (target: HTMLElement) => {
@@ -143,7 +146,7 @@ export default function Login() {
};
return (
-
{getPageTitle('Login')}
-
+
{contentType === 'image' && contentPosition !== 'background' ? imageBlock(illustrationImage) : null}
{contentType === 'video' && contentPosition !== 'background' ? videoBlock(illustrationVideo) : null}
-
+
-
-
- {title}
-
-
-
-
-
Use{' '}
- setLogin(e.target)}>admin@flatlogic.com{' / '}
- 8e470127{' / '}
- to login as Admin
-
Use setLogin(e.target)}>client@hello.com{' / '}
- f04a8902244c{' / '}
- to login as User
-
-
-
-
+
+
{title}
+
THE FUTURE OF SOUND
+
+
+
+
+
+
-
-
-
+
handleSubmit(values)}
>
-
-
© 2026 {title}. © All rights reserved
-
+
+
© 2026 {title}. Built for Creators.
+
Privacy Policy
-
+
);
}
Login.getLayout = function getLayout(page: ReactElement) {
return {page};
-};
+};
\ No newline at end of file
diff --git a/frontend/src/pages/register.tsx b/frontend/src/pages/register.tsx
index 73a3987..d245f78 100644
--- a/frontend/src/pages/register.tsx
+++ b/frontend/src/pages/register.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
import type { ReactElement } from 'react';
import { ToastContainer, toast } from 'react-toastify';
import Head from 'next/head';
@@ -12,78 +12,138 @@ import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { useRouter } from 'next/router';
import { getPageTitle } from '../config';
+import BaseIcon from '../components/BaseIcon';
+import { mdiMusic, mdiContentCopy, mdiCheckDecagram } from '@mdi/js';
+import Link from 'next/link';
import axios from "axios";
+import jwt from 'jsonwebtoken';
export default function Register() {
const [loading, setLoading] = React.useState(false);
+ const [accessCode, setAccessCode] = useState(null);
const router = useRouter();
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
-
const handleSubmit = async (value) => {
setLoading(true)
try {
+ const { data: token } = await axios.post('/auth/signup', value);
+ const decoded: any = jwt.decode(token);
- const { data: response } = await axios.post('/auth/signup',value);
- await router.push('/login')
+ if (decoded && decoded.user && decoded.user.accessCode) {
+ setAccessCode(decoded.user.accessCode);
+ notify('success', 'Account created! Here is your access code.');
+ } else {
+ await router.push('/login')
+ notify('success', 'Account created! Please login.')
+ }
setLoading(false)
- notify('success', 'Please check your email for verification link')
} catch (error) {
setLoading(false)
console.log('error: ', error)
- notify('error', 'Something was wrong. Try again')
+ notify('error', 'Something went wrong. Try again')
}
};
+ const copyToClipboard = () => {
+ if (accessCode) {
+ navigator.clipboard.writeText(accessCode);
+ notify('info', 'Code copied to clipboard!');
+ }
+ }
+
return (
- <>
+
-
{getPageTitle('Login')}
+
{getPageTitle('Register')}
-
-
- handleSubmit(values)}
- >
-
);
}
diff --git a/frontend/src/pages/studio.tsx b/frontend/src/pages/studio.tsx
new file mode 100644
index 0000000..42ca860
--- /dev/null
+++ b/frontend/src/pages/studio.tsx
@@ -0,0 +1,272 @@
+import {
+ mdiMusic,
+ mdiRobotOutline,
+ mdiPlus,
+ mdiPlay,
+ mdiPiano,
+ mdiGuitarAcoustic,
+ mdiMicrophone,
+ mdiTuneVariant
+} from '@mdi/js';
+import Head from 'next/head';
+import React, { ReactElement, useEffect, useState } from 'react';
+import CardBox from '../components/CardBox';
+import LayoutAuthenticated from '../layouts/Authenticated';
+import SectionMain from '../components/SectionMain';
+import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
+import { getPageTitle } from '../config';
+import BaseIcon from '../components/BaseIcon';
+import BaseButton from '../components/BaseButton';
+import FormField from '../components/FormField';
+import BaseDivider from '../components/BaseDivider';
+import axios from 'axios';
+import { useAppDispatch, useAppSelector } from '../stores/hooks';
+import { aiResponse } from '../stores/openAiSlice';
+import { toast, ToastContainer } from 'react-toastify';
+
+const Studio = () => {
+ const dispatch = useAppDispatch();
+ const { currentUser } = useAppSelector((state) => state.auth);
+ const { isAskingResponse, aiResponse: gptResult } = useAppSelector((state) => state.openAi);
+
+ const [prompt, setPrompt] = useState('');
+ const [style, setStyle] = useState('Pop');
+ const [projects, setProjects] = useState([]);
+ const [instruments, setInstruments] = useState([]);
+ const [loading, setLoading] = useState(false);
+
+ useEffect(() => {
+ fetchStudioData();
+ }, []);
+
+ const fetchStudioData = async () => {
+ try {
+ setLoading(true);
+ const [projRes, instRes] = await Promise.all([
+ axios.get('/projects?limit=5'),
+ axios.get('/instruments?limit=8')
+ ]);
+ setProjects(projRes.data.rows || []);
+ setInstruments(instRes.data.rows || []);
+ } catch (error) {
+ console.error('Error fetching studio data:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleAiGenerate = async () => {
+ if (!prompt) {
+ toast.error('Please enter an idea for your song');
+ return;
+ }
+
+ const fullPrompt = `Create a song structure based on this idea: "${prompt}". Style: ${style}. Return a JSON with title, lyrics (verses, chorus), and suggested instruments.`;
+
+ dispatch(aiResponse({
+ input: [
+ { role: 'system', content: 'You are a professional music producer and songwriter.' },
+ { role: 'user', content: fullPrompt },
+ ],
+ options: { poll_interval: 5, poll_timeout: 300 },
+ }));
+ };
+
+ useEffect(() => {
+ if (gptResult) {
+ toast.success('AI has generated your song structure!');
+ // In a real app, we would save this as a new project
+ }
+ }, [gptResult]);
+
+ return (
+ <>
+
+ {getPageTitle('Musical Studio')}
+
+
+
+ toast.info('Manual project creation coming soon!')}
+ />
+
+
+
+ {/* AI Generator Section */}
+
+
+
+
+
+
+
+
+ AI SONGWRITER
+
+
Describe your idea, choose a style, and let AI build the foundation of your next hit.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {gptResult && (
+
+ Generated Structure
+
+
+ {typeof gptResult === 'string' ? gptResult : JSON.stringify(gptResult, null, 2)}
+
+
+
+
+
+
+
+ )}
+
+
+
+ {projects.length > 0 ? (
+
+ {projects.map((project: any) => (
+
+
+
+
+
+
+
{project.name || 'Untitled Project'}
+
{project.genre?.name || 'No Genre'}
+
+
+
+
+ ))}
+
+
+ ) : (
+
+
No projects yet. Start by generating one!
+
+ )}
+
+
+
+
+ {instruments.map((inst: any) => (
+
+
+ {inst.name}
+
+ ))}
+
+
+ Add More
+
+
+
+
+
+
+ {/* Sidebar / Quick Settings */}
+
+
+
+
+
+ Master Volume
+ 85%
+
+
+
+
+
+
+
+
+
+
Active Effects
+
+ {['Reverb', 'Compressor', 'Delay'].map(fx => (
+
+ {fx}
+
+ ))}
+
+
+
+
+
+
+
+
GO PRO
+
Unlock unlimited AI generations and 500+ premium instruments.
+
+
+
+
+
+
+
+ >
+ );
+};
+
+Studio.getLayout = function getLayout(page: ReactElement) {
+ return {page};
+};
+
+export default Studio;
\ No newline at end of file
diff --git a/frontend/src/stores/authSlice.ts b/frontend/src/stores/authSlice.ts
index 2eaa1f2..8fe1410 100644
--- a/frontend/src/stores/authSlice.ts
+++ b/frontend/src/stores/authSlice.ts
@@ -40,6 +40,36 @@ export const loginUser = createAsyncThunk(
}
);
+export const loginWithCode = createAsyncThunk(
+ 'auth/loginWithCode',
+ async (creds: { code: string }, { rejectWithValue }) => {
+ try {
+ const response = await axios.post('auth/signin/code', creds);
+ return response.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+ return rejectWithValue(error.response.data);
+ }
+ }
+);
+
+export const signupUser = createAsyncThunk(
+ 'auth/signupUser',
+ async (creds: Record, { rejectWithValue }) => {
+ try {
+ const response = await axios.post('auth/signup', creds);
+ return response.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+ return rejectWithValue(error.response.data);
+ }
+ }
+);
+
export const passwordReset = createAsyncThunk(
'auth/passwordReset',
async (value: Record, { rejectWithValue }) => {
@@ -79,10 +109,7 @@ export const authSlice = createSlice({
},
},
extraReducers: (builder) => {
- builder.addCase(loginUser.pending, (state) => {
- state.isFetching = true;
- });
- builder.addCase(loginUser.fulfilled, (state, action) => {
+ const handleAuthFulfilled = (state, action) => {
const token = action.payload;
const user = jwt.decode(token);
@@ -91,12 +118,36 @@ export const authSlice = createSlice({
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
- });
+ state.isFetching = false;
+ };
+ builder.addCase(loginUser.pending, (state) => {
+ state.isFetching = true;
+ });
+ builder.addCase(loginUser.fulfilled, handleAuthFulfilled);
builder.addCase(loginUser.rejected, (state, action) => {
state.errorMessage = String(action.payload) || 'Something went wrong. Try again';
state.isFetching = false;
});
+
+ builder.addCase(loginWithCode.pending, (state) => {
+ state.isFetching = true;
+ });
+ builder.addCase(loginWithCode.fulfilled, handleAuthFulfilled);
+ builder.addCase(loginWithCode.rejected, (state, action) => {
+ state.errorMessage = String(action.payload) || 'Invalid access code';
+ state.isFetching = false;
+ });
+
+ builder.addCase(signupUser.pending, (state) => {
+ state.isFetching = true;
+ });
+ builder.addCase(signupUser.fulfilled, handleAuthFulfilled);
+ builder.addCase(signupUser.rejected, (state, action) => {
+ state.errorMessage = String(action.payload) || 'Something went wrong. Try again';
+ state.isFetching = false;
+ });
+
builder.addCase(findMe.pending, () => {
console.log('Pending findMe');
});
@@ -121,4 +172,4 @@ export const authSlice = createSlice({
// Action creators are generated for each case reducer function
export const { logoutUser } = authSlice.actions;
-export default authSlice.reducer;
+export default authSlice.reducer;
\ No newline at end of file