Here's a structured approach to building a MERN stack flight booking application with directories, files, and code snippets. You'll find a guide for setting up the backend and frontend, including the basic code required for each part of the project. We’ll encapsulate everything needed to get started.

Project Structure

flight-booking-app/
├── client/
│   ├── public/
│   │   ├── index.html
│   ├── src/
│   │   ├── components/
│   │   │   ├── Login.js
│   │   │   ├── Signup.js
│   │   │   ├── FlightSearch.js
│   │   │   └── Dashboard.js
│   │   ├── App.js
│   │   ├── index.js
│   │   ├── styles.css
├── server/
│   ├── models/
│   │   ├── User.js
│   │   ├── Flight.js
│   │   └── Booking.js
│   ├── routes/
│   │   ├── auth.js
│   │   ├── flights.js
│   │   └── bookings.js
│   ├── .env
│   ├── server.js
│   └── package.json
└── README.md
Backend Setup in server Directory
Initialize Node.js Application: Navigate to server directory and set up Node.js:

mkdir server
cd server
npm init -y
npm install express mongoose bcryptjs jsonwebtoken dotenv cors
Create server.js:

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
app.use(express.json());
app.use(cors());

const authRoutes = require('./routes/auth');
const flightRoutes = require('./routes/flights');
const bookingRoutes = require('./routes/bookings');

app.use('/api/auth', authRoutes);
app.use('/api/flights', flightRoutes);
app.use('/api/bookings', bookingRoutes);

mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log('MongoDB connected'))
  .catch(err => console.error('MongoDB connection error:', err));

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Create Models: User Model (models/User.js)

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  role: { type: String, default: 'user', enum: ['user', 'admin'] },
});

module.exports = mongoose.model('User', UserSchema);
Flight Model (models/Flight.js)

const mongoose = require('mongoose');

const FlightSchema = new mongoose.Schema({
  flightNumber: String,
  departure: String,
  destination: String,
  date: Date,
  time: String,
  seatsAvailable: Number,
  price: Number,
});

module.exports = mongoose.model('Flight', FlightSchema);
Booking Model (models/Booking.js)

const mongoose = require('mongoose');

const BookingSchema = new mongoose.Schema({
  user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
  flight: { type: mongoose.Schema.Types.ObjectId, ref: 'Flight', required: true },
  seatsBooked: [String],
  bookingDate: { type: Date, default: Date.now },
  totalCost: Number,
  paymentStatus: { type: String, enum: ['pending', 'completed', 'failed'], default: 'pending' },
});

module.exports = mongoose.model('Booking', BookingSchema);
Create Routes: Auth Routes (routes/auth.js)

const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User');

const router = express.Router();

router.post('/signup', async (req, res) => {
  try {
    const { name, email, password } = req.body;
    const hashedPassword = await bcrypt.hash(password, 10);

    const newUser = new User({ name, email, password: hashedPassword });
    await newUser.save();

    const token = jwt.sign({ id: newUser._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
    res.json({ token });
  } catch (error) {
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.post('/login', async (req, res) => {
  try {
    const { email, password } = req.body;
    const user = await User.findOne({ email });

    if (!user) return res.status(400).json({ error: 'Invalid credentials' });

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) return res.status(400).json({ error: 'Invalid credentials' });

    const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
    res.json({ token });
  } catch (error) {
    res.status(500).json({ error: 'Internal server error' });
  }
});

module.exports = router;
Flight Routes (routes/flights.js)

const express = require('express');
const Flight = require('../models/Flight');

const router = express.Router();

router.get('/', async (req, res) => {
  try {
    const flights = await Flight.find(req.query);
    res.json(flights);
  } catch (error) {
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.post('/', async (req, res) => {
  try {
    const flight = new Flight(req.body);
    await flight.save();
    res.status(201).json(flight);
  } catch (error) {
    res.status(500).json({ error: 'Internal server error' });
  }
});

module.exports = router;
Configure Environment Variables (.env):

MONGODB_URI=mongodb+srv://<username>:<password>@cluster0.mongodb.net/flightBookingDB?retryWrites=true&w=majority
JWT_SECRET=your_jwt_secret_key
Frontend Setup in client Directory
Initialize React App: Navigate to client directory and set up React:

npx create-react-app client
cd client
npm install axios bootstrap react-icons react-router-dom
Setup Bootstrap and Basic Routing: index.js (client/src/)

import 'bootstrap/dist/css/bootstrap.min.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
import './styles.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>
);
Main App Component with Routes (App.js):

import React from 'react';
import { Route, Routes } from 'react-router-dom';
import Login from './components/Login';
import Signup from './components/Signup';
import FlightSearch from './components/FlightSearch';
import Dashboard from './components/Dashboard';

const App = () => (
  <div className="container my-5">
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path="/signup" element={<Signup />} />
      <Route path="/search" element={<FlightSearch />} />
      <Route path="/dashboard" element={<Dashboard />} />
      <Route path="/" element={<FlightSearch />} />
    </Routes>
  </div>
);

export default App;
Key UI Components: Login Component (Login.js):

import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import { FaLock, FaEnvelope } from 'react-icons/fa';

const Login = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const navigate = useNavigate();

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await axios.post('http://localhost:5000/api/auth/login', { email, password });
      localStorage.setItem('token', response.data.token);
      navigate('/search');
    } catch (error) {
      console.error('Login failed', error);
    }
  };

  return (
    <div className="d-flex justify-content-center align-items-center" style={{ height: '100vh' }}>
      <form onSubmit={handleSubmit} className="p-4 border rounded shadow">
        <h2 className="mb-4 text-center">Login</h2>
        <div className="mb-3">
          <label className="form-label"><FaEnvelope /> Email</label>
          <input type="email" className="form-control" value={email} onChange={(e) => setEmail(e.target.value)} required />
        </div>
        <div className="mb-3">
          <label className="form-label"><FaLock /> Password</label>
          <input type="password" className="form-control" value={password} onChange={(e) => setPassword(e.target.value)} required />
        </div>
        <div className="text-center">
          <button type="submit" className="btn btn-primary btn-block">Login</button>
        </div>
      </form>
    </div>
  );
};

export default Login;
Signup Component (Signup.js):

import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import { FaUser, FaEnvelope, FaLock } from 'react-icons/fa';

const Signup = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const navigate = useNavigate();

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await axios.post('http://localhost:5000/api/auth/signup', { name, email, password });
      navigate('/login');
    } catch (error) {
      console.error('Signup failed', error);
    }
  };

  return (
    <div className="d-flex justify-content-center align-items-center" style={{ height: '100vh' }}>
      <form onSubmit={handleSubmit} className="p-4 border rounded shadow">
        <h2 className="mb-4 text-center">Signup</h2>
        <div className="mb-3">
          <label className="form-label"><FaUser /> Name</label>
          <input type="text" className="form-control" value={name} onChange={(e) => setName(e.target.value)} required />
        </div>
        <div className="mb-3">
          <label className="form-label"><FaEnvelope /> Email</label>
          <input type="email" className="form-control" value={email} onChange={(e) => setEmail(e.target.value)} required />
        </div>
        <div className="mb-3">
          <label className="form-label"><FaLock /> Password</label>
          <input type="password" className="form-control" value={password} onChange={(e) => setPassword(e.target.value)} required />
        </div>
        <div className="text-center">
          <button type="submit" className="btn btn-primary btn-block">Signup</button>
        </div>
      </form>
    </div>
  );
};

export default Signup;
FlightSearch Component (FlightSearch.js):

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { FaPlane } from 'react-icons/fa';

const FlightSearch = () => {
  const [flights, setFlights] = useState([]);

  useEffect(() => {
    const fetchFlights = async () => {
      try {
        const response = await axios.get('http://localhost:5000/api/flights');
        setFlights(response.data);
      } catch (error) {
        console.error('Error fetching flights', error);
      }
    };
    fetchFlights();
  }, []);

  return (
    <div className="container my-5">
      <h2 className="text-center mb-4"><FaPlane /> Available Flights</h2>
      <div className="list-group">
        {flights.map(flight => (
          <a key={flight._id} href={`/booking/${flight._id}`} className="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
            {flight.flightNumber}: {flight.departure} to {flight.destination}
            <span className="badge bg-primary rounded-pill">{flight.date}</span>
          </a>
        ))}
      </div>
    </div>
  );
};

export default FlightSearch;
Running the Application
Start Backend Server: Navigate to the server directory:

cd server
npm start
Start Frontend Client: Navigate to the client directory:

cd client
npm start
Final Steps
Make sure MongoDB Atlas and environment variables are properly configured so your app can connect to the database without any issues.
Include error handling and validations in your final application to manage any exceptions effectively.
Adjust any configurations as necessary for production, such as utilizing a build of the frontend from create-react-app.
This structure provides a clean and organized way to build your MERN stack application with essential project files and code. Expand the components and models with more functionality as required for your specific needs.