Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"@heroicons/react": "2.0.18",
"@material-tailwind/react": "2.1.4",
"apexcharts": "3.44.0",
"axios": "^1.12.2",
"jwt-decode": "^4.0.0",
"prop-types": "15.8.1",
"react": "18.2.0",
"react-apexcharts": "1.4.1",
Expand All @@ -27,6 +29,6 @@
"prettier": "3.0.3",
"prettier-plugin-tailwindcss": "0.5.6",
"tailwindcss": "3.3.4",
"vite": "4.5.0"
"vite": "^4.5.14"
}
}
}
Binary file added public/img/background.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/img/pattern.png
Binary file not shown.
17 changes: 15 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { Routes, Route, Navigate } from "react-router-dom";
import { Dashboard, Auth } from "@/layouts";
import PrivateRoute from "../src/component/PrivateRoute";

function App() {
return (
<Routes>
<Route path="/dashboard/*" element={<Dashboard />} />
{/* Dashboard'u sadece giriş yapmış kullanıcı görecek */}
<Route
path="/dashboard/*"
element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}
/>

{/* Auth sayfaları (giriş, kayıt) herkes görebilir */}
<Route path="/auth/*" element={<Auth />} />
<Route path="*" element={<Navigate to="/dashboard/home" replace />} />

{/* Varsayılan yönlendirme */}
<Route path="*" element={<Navigate to="/auth/sign-in" replace />} />
</Routes>
);
}
Expand Down
29 changes: 29 additions & 0 deletions src/api/axiosConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import axios from "axios";



const apiClient = axios.create({
baseURL: "https://localhost:7093/api",
});


apiClient.interceptors.request.use(
(config) => {

const token = localStorage.getItem("authToken");


if (token) {

config.headers.Authorization = `Bearer ${token}`;
}

return config;
},
(error) => {

return Promise.reject(error);
}
);

export default apiClient;
15 changes: 15 additions & 0 deletions src/component/PrivateRoute.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { Navigate } from "react-router-dom";

const PrivateRoute = ({ children }) => {
const token = localStorage.getItem("authToken");

if (!token) {
// Token yoksa login sayfasına yönlendir
return <Navigate to="/auth/sign-in" replace />;
}

return children;
};

export default PrivateRoute;
34 changes: 22 additions & 12 deletions src/context/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export function reducer(state, action) {
}
case "OPEN_CONFIGURATOR": {
return { ...state, openConfigurator: action.value };
}
// YENİ: Kullanıcı rolünü ayarlamak için yeni case eklendi.
case "SET_USER_ROLE": {
return { ...state, userRole: action.value };
}
default: {
throw new Error(`Unhandled action type: ${action.type}`);
Expand All @@ -38,18 +42,20 @@ export function MaterialTailwindControllerProvider({ children }) {
transparentNavbar: true,
fixedNavbar: false,
openConfigurator: false,
// YENİ: userRole state'i eklendi. Sayfa yenilendiğinde rolün kaybolmaması için localStorage'dan okunuyor.
userRole: localStorage.getItem("userRole") || null,
};

const [controller, dispatch] = React.useReducer(reducer, initialState);
const value = React.useMemo(
() => [controller, dispatch],
[controller, dispatch]
() => [controller, dispatch],
[controller, dispatch]
);

return (
<MaterialTailwind.Provider value={value}>
{children}
</MaterialTailwind.Provider>
<MaterialTailwind.Provider value={value}>
{children}
</MaterialTailwind.Provider>
);
}

Expand All @@ -58,7 +64,7 @@ export function useMaterialTailwindController() {

if (!context) {
throw new Error(
"useMaterialTailwindController should be used inside the MaterialTailwindControllerProvider."
"useMaterialTailwindController should be used inside the MaterialTailwindControllerProvider."
);
}

Expand All @@ -72,14 +78,18 @@ MaterialTailwindControllerProvider.propTypes = {
};

export const setOpenSidenav = (dispatch, value) =>
dispatch({ type: "OPEN_SIDENAV", value });
dispatch({ type: "OPEN_SIDENAV", value });
export const setSidenavType = (dispatch, value) =>
dispatch({ type: "SIDENAV_TYPE", value });
dispatch({ type: "SIDENAV_TYPE", value });
export const setSidenavColor = (dispatch, value) =>
dispatch({ type: "SIDENAV_COLOR", value });
dispatch({ type: "SIDENAV_COLOR", value });
export const setTransparentNavbar = (dispatch, value) =>
dispatch({ type: "TRANSPARENT_NAVBAR", value });
dispatch({ type: "TRANSPARENT_NAVBAR", value });
export const setFixedNavbar = (dispatch, value) =>
dispatch({ type: "FIXED_NAVBAR", value });
dispatch({ type: "FIXED_NAVBAR", value });
export const setOpenConfigurator = (dispatch, value) =>
dispatch({ type: "OPEN_CONFIGURATOR", value });
dispatch({ type: "OPEN_CONFIGURATOR", value });


export const setUserRole = (dispatch, value) =>
dispatch({ type: "SET_USER_ROLE", value });
82 changes: 41 additions & 41 deletions src/layouts/dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,53 @@ import { Routes, Route } from "react-router-dom";
import { Cog6ToothIcon } from "@heroicons/react/24/solid";
import { IconButton } from "@material-tailwind/react";
import {
Sidenav,
DashboardNavbar,
Configurator,
Footer,
  Sidenav,
  DashboardNavbar,
  Configurator,
  Footer,
} from "@/widgets/layout";
import routes from "@/routes";
import { useMaterialTailwindController, setOpenConfigurator } from "@/context";

export function Dashboard() {
const [controller, dispatch] = useMaterialTailwindController();
const { sidenavType } = controller;
  const [controller, dispatch] = useMaterialTailwindController();
  const { sidenavType } = controller;

return (
<div className="min-h-screen bg-blue-gray-50/50">
<Sidenav
routes={routes}
brandImg={
sidenavType === "dark" ? "/img/logo-ct.png" : "/img/logo-ct-dark.png"
}
/>
<div className="p-4 xl:ml-80">
<DashboardNavbar />
<Configurator />
<IconButton
size="lg"
color="white"
className="fixed bottom-8 right-8 z-40 rounded-full shadow-blue-gray-900/10"
ripple={false}
onClick={() => setOpenConfigurator(dispatch, true)}
>
<Cog6ToothIcon className="h-5 w-5" />
</IconButton>
<Routes>
{routes.map(
({ layout, pages }) =>
layout === "dashboard" &&
pages.map(({ path, element }) => (
<Route exact path={path} element={element} />
))
)}
</Routes>
<div className="text-blue-gray-600">
<Footer />
</div>
</div>
</div>
);
  return (
    <div className="min-h-screen bg-blue-gray-50/50">
      <Sidenav
        routes={routes}
        brandImg={
          sidenavType === "dark" ? "/img/logo-ct.png" : "/img/logo-ct-dark.png"
        }
      />
      <div className="p-4 xl:ml-80">
        <DashboardNavbar />
        <Configurator />
        <IconButton
          size="lg"
          color="white"
          className="fixed bottom-8 right-8 z-40 rounded-full shadow-blue-gray-900/10"
          ripple={false}
          onClick={() => setOpenConfigurator(dispatch, true)}
        >
          <Cog6ToothIcon className="h-5 w-5" />
        </IconButton>
        <Routes>
          {routes.map(
            ({ layout, pages }) =>
              layout === "dashboard" &&
              pages.map(({ path, element }) => (
                <Route exact path={path} element={element} />
              ))
          )}
        </Routes>
        <div className="text-blue-gray-600">
          <Footer />
        </div>
      </div>
    </div>
  );
}

Dashboard.displayName = "/src/layout/dashboard.jsx";
Expand Down
2 changes: 1 addition & 1 deletion src/pages/auth/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "@/pages/auth/sign-in";
export * from "@/pages/auth/sign-up";

Loading