Level 1 Team Project

Level 1 Projects

1. ATM Bank Terminal Simulator

This guide is tailored for students who want to build an ATM terminal-like application using React and Vite frameworks, based on the files and designs you've shared.

Step 1: Initialize the Project

1. Create a new React + Vite project:

npm create vite@latest million-dollar-bank -- --template react
cd million-dollar-bank
npm install

2. Install dependencies (if you use additional ones like React Router or icons):

Step 2: Set Up Project Structure

  1. Structure your folders as follows:

/src
  /components
    Header.jsx
    Footer.jsx
    Message.jsx
  App.jsx
  main.jsx
/style.css
/index.html
  1. Add the provided App.jsx and style.css into your /src and root respectively.

// App.jsx
import React from "react"
import Message from "./components/Message"
import Header from "./components/Header"
import Footer from "./components/Footer"

export default function App() {
	const passCode = "1001"

	const [userInput, setUserInput] = React.useState({
		charOne: "",
		charTwo: "",
		charThree: "",
		charFour: "",
	})
	
	const [verified, setVerified] = React.useState(undefined)

	function handleChange(event) {
		setUserInput(prev => ({...prev, [event.target.name]: event.target.value }))
	}
	
	function handleSubmit(event) {
		event.preventDefault()
		const combinedInput = Object.values(userInput).join("")
		setVerified(combinedInput === passCode)
	}

	return (
    <div className="wrapper">
      <Header />

      <form onSubmit={handleSubmit}>
        <div>
          <input
            required
            type="password"
            name="charOne"
            maxLength="1"
            onChange={handleChange}
          />

          <input
            required
            type="password"
            name="charTwo"
            maxLength="1"
            onChange={handleChange}
          />

          <input
            required
            type="password"
            name="charThree"
            maxLength="1"
            onChange={handleChange}
          />

          <input
            required
            type="password"
            name="charFour"
            maxLength="1"
            onChange={handleChange}
          />
        </div>

        <button disabled={verified}>Submit</button>
        <Message status={verified} />
      </form>

      <Footer />
    </div>
  )
}

Step 3: Build Components

  1. Header.jsx

// Header.jsx
export default function Header() {
    return <header><h1>KOIDA Financial Services</h1></header>;
}
  1. Footer.jsx

// Footer.jsx
export default function Footer() {
    return <footer><h1>Current Balance: $1,000,000</h1></footer>;
}
  1. Message.jsx

// Message.jsx
export default function Message({ status }) {
    if (status === undefined) return null;
    return (
        <div className="message-container">
            <p className="message">
                {status ? 'Access Granted. Welcome!' : 'Access Denied. Try Again.'}
            </p>
        </div>
    );
}

Step 4: Complete App.jsx Logic

Your App.jsx file is already well-implemented based on the challenge!

  • State management for user inputs.

  • handleChange() function updates state dynamically.

  • handleSubmit() prevents page reload, checks input against passCode, and sets verification state.

  • DRY (Don't Repeat Yourself) principle is followed by using common handlers.

Step 5: Apply Styling

Use the provided style.css. Add it to your main.jsx:

// main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import './style.css';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
);

Step 6: Add Background Image

Place the background image in /public/images/ folder, and ensure the path in style.css matches:

// Some code
background: url(./images/bady-abbas-c4XoMGxfsVU-unsplash.jpg);

Step 7: Test the App

Run the development server:

npm run dev

Output

Check if:

  • ✅ You can enter the 4-digit code.

  • ✅ The correct code (1001) grants access.

  • ✅ Any other code denies access.

  • ✅ Styling matches the provided screenshot.

Step 8 (Optional): Improvements 🚀

  • Auto-focus to the next input box after typing.

  • Add animations or transitions on success/fail.

  • Add sound effects for success/error.

  • Save "verified" state in localStorage.

Let's expand the app with two exciting features: PIN entry animations and auto-tab functionality!

Step 9: Add PIN Entry Animations

  1. Update the CSS for Input Animations

In your style.css, add:

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}

input:focus {
  animation: pulse 0.3s ease-in-out;
}

This gives a nice pulse effect when typing PIN numbers.

  1. Add Shake Animation for Incorrect PIN

In style.css, add:

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}

.shake {
  animation: shake 0.3s;
}
  1. Apply Class Conditionally in App.jsx

Update your <form> tag in App.jsx to conditionally apply the shake animation:

// App.jsx snippet
<form onSubmit={handleSubmit} className={verified === false ? 'shake' : ''}>

Step 10: Add Auto-Tab Functionality

  1. Enhance handleChange() function in App.jsx:

// App.jsx snippet
function handleChange(event) {
  const { name, value, nextSibling } = event.target;

  setUserInput(prev => ({ ...prev, [name]: value }));

  if (value && nextSibling && nextSibling.tagName === 'INPUT') {
    nextSibling.focus();
  }
}

Step 11: Test New Features 🚀

Run your app and test:

  • ✅ Inputs pulse on focus.

  • ✅ Form shakes when the wrong PIN is entered.

  • ✅ Cursor auto-moves to the next input.

Modify the Footer component so as to display the balance when correct pin is entered. If PIN is entered incorrectly, warning red shield icon is displayed. If PIN is correctly verified, green shieled icon is displayed.

  1. Install React Icons Library (optional but recommended):

npm install react-icons
  1. Update Footer.jsx Component:

// Updated Footer.jsx
import { FaShieldAlt } from 'react-icons/fa';
import { MdWarning } from 'react-icons/md';

export default function Footer({ status }) {
    return (
        <footer>
            {status === undefined && <h1>Please enter your PIN</h1>}
            {status === true && (
                <h1>
                    Current Balance: $1,000,000 {' '}
                    <FaShieldAlt style={{ color: 'limegreen' }} />
                </h1>
            )}
            {status === false && (
                <h1>
                    Access Denied {' '}
                    <MdWarning style={{ color: 'red' }} />
                </h1>
            )}
        </footer>
    );
}
  1. Pass Status Prop from App.jsx:

In App.jsx, update your Footer component usage:

// App.jsx snippet
<Footer status={verified} />
  1. Test:

  • ✅ Enter correct PIN → Balance with green shield icon.

  • ✅ Enter incorrect PIN → Warning with red icon.

  • ✅ Before input → Prompt message "Please enter your PIN".

Output:


Last updated