Quickstart Guide
This section walks you through adding a new feature to CRADLE. It is divided into the following parts:
Adding a File
To add a new feature, create a folder in the /components
directory for your new component. For example, to add a Random Number component, create:
src/
└── renderer/
└── src/
└── components/
└── RandomNumber/
├── RandomNumber.jsx
└── RandomNumber.test.jsx
This “folder-per-file” structure is applied across components, hooks, services, and utils.
Creating the Component
1. Utility Function
Create a utility function to generate a random number:
// /utils/numberUtils/numberUtils.js
/**
* Generates a random number between 1 and max.
* @param {number} max - The maximum value.
* @returns {number} A random number.
*/
const getRandomNumber = (max) => Math.floor(Math.random() * max) + 1;
export { getRandomNumber };
2. Custom Hook
Define a hook that uses the utility to manage random number state:
// /hooks/useRandomNumber/useRandomNumber.js
import { useState } from 'react';
import { getRandomNumber } from '../../utils/numberUtils/numberUtils';
/**
* Returns a random number and a function to update it.
* @param {number} max - Maximum number (default: 100).
* @returns {[number, function]} The random number and an updater function.
*/
const useRandomNumber = (max = 100) => {
const [number, setNumber] = useState(getRandomNumber(max));
const generateRandomNumber = () => setNumber(getRandomNumber(max));
return [number, generateRandomNumber];
};
export default useRandomNumber;
3. Service Function
Create a service function to save the number:
// /services/numberService/numberService.js
import { authAxios } from '../axiosInstance/axiosInstance';
/**
* Saves the random number to the backend.
* @param {number} number - The number to save.
* @returns {Promise} Axios promise.
*/
const saveNumber = (number) => {
return authAxios({
method: 'POST',
url: '/numbers/',
data: { number },
});
};
export { saveNumber };
4. The RandomNumber Component
Implement the component that displays the random number and provides controls:
// /components/RandomNumber/RandomNumber.jsx
import React from 'react';
import useRandomNumber from '../../hooks/useRandomNumber/useRandomNumber';
import { saveNumber } from '../../services/numberService/numberService';
import useNavbarContents from '../../hooks/useNavbarContents/useNavbarContents';
import NavbarButton from '../NavbarButton/NavbarButton';
/**
* Displays a random number with options to save or generate a new number.
*/
export default function RandomNumber() {
const [randomNumber, generateRandomNumber] = useRandomNumber(100);
const handleSaveNumber = () => {
saveNumber(randomNumber)
.then(() => console.log('Number saved successfully!'))
.catch((error) => console.log(error));
};
useNavbarContents(
<NavbarButton
key="save-random-number-btn"
icon={/* Insert a valid JSX icon element */}
text="Save This Number"
onClick={handleSaveNumber}
data-testid="save-random-number-btn"
/>,
[handleSaveNumber]
);
return (
<div>
<h2>Random Number: {randomNumber}</h2>
<button
className="btn btn-primary"
onClick={handleSaveNumber}
data-testid="save-random-number-btn"
>
Save This Number
</button>
<button className="btn btn-secondary" onClick={generateRandomNumber}>
Generate New Number
</button>
</div>
);
}
# Adding It to the App Component
Integrate your new component by adding a route in your main app file. For example:
```jsx
// App.jsx
import { HashRouter, Routes, Route } from 'react-router-dom';
import AuthProvider from './components/AuthProvider/AuthProvider.jsx';
import PrivateRoute from './components/PrivateRoute/PrivateRoute.jsx';
import Home from './components/Home/Home.jsx';
import RandomNumber from './components/RandomNumber/RandomNumber.jsx';
import NotFound from './components/NotFound/NotFound.jsx';
function App() {
return (
<HashRouter>
<AuthProvider>
<Routes>
<Route element={<PrivateRoute fallback="/login" />}>
<Route path="/" element={<Home />}>
<Route path="/random-number" element={<RandomNumber />} />
</Route>
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
</AuthProvider>
</HashRouter>
);
}
export default App;
Key Concepts
- HashRouter: Enables client-side routing in Electron. Learn more.
- AuthProvider: Provides client-side authentication.
- PrivateRoute: Protects routes by checking user authentication.
- Home: Main container that includes the navbar and sidebar.
- Navbar & useNavbarContents: Allows dynamic addition of buttons (e.g., the “Save This Number” button).
- Sidebar: Navigation component. To add an item, see the example below:
// /components/Sidebar/Sidebar.jsx
import { useNavigate } from 'react-router-dom';
import SidebarSection from './SidebarSection';
import SidebarItem from './SidebarItem';
import { useCallback } from 'react';
export default function Sidebar() {
const navigate = useNavigate();
const randomNumberLocation = '/random-number';
const handleRandomNumber = useCallback(() => {
navigate(randomNumberLocation);
}, [navigate]);
return (
<SidebarSection sectionType="header" height="fit" justify="start">
<SidebarItem
handleClick={handleRandomNumber}
icon={/* Insert a valid JSX icon element */}
text="Random Number"
highlightedLocation={randomNumberLocation}
/>
</SidebarSection>
);
}
Last updated on