sample coding

app.py

from flask import Flask, request, jsonify, session
from flask_cors import CORS
import pymysql  # MySQL library
import requests
from werkzeug.security import generate_password_hash, check_password_hash
from retrying import retry
import requests

app = Flask(__name__)
app.secret_key = '2576fa35bdb55ddfd7476f752939fa7e'
CORS(app)

# Database Configuration (Using pymysql)
db = pymysql.connect(
    host="localhost",
    user="root",  # Replace with your MySQL username
    password="",  # Replace with your MySQL password
    database="recipe_finder"  # Ensure the database exists
)

SPOONACULAR_API_KEY = "4cf45fa4ab174fb5bcd586e17b02a653"  # Replace with your real API key

@app.route('/', methods=['GET'])
def home():
    return jsonify({"message": "Welcome to the Recipe Finder API. Use the /find-recipes endpoint to search for recipes."})

@app.route('/signup', methods=['POST'])
def signup():
    data = request.get_json()  # Corrected to safely fetch JSON data
    if not data:
        return jsonify({'message': 'No input data provided'}), 400

    user_name = data.get('user_name')  # Ensure consistent key
    password = data.get('password')    # Use the correct key for password

    if not user_name or not password:
        return jsonify({'message': 'Username and password are required'}), 400

    hashed_password = generate_password_hash(password)
    cur = db.cursor()
    cur.execute("SELECT * FROM users WHERE user_name=%s", (user_name,))
    user = cur.fetchone()
    if user:
        cur.close()
        return jsonify({'message': 'Username already registered'}), 400

    cur.execute("INSERT INTO users (user_name, password) VALUES (%s, %s)", (user_name, hashed_password))
    db.commit()
    cur.close()

    return jsonify({'message': 'Signup successful!'})

@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()  # Corrected to safely fetch JSON data
    if not data:
        return jsonify({'message': 'No input data provided'}), 400

    user_name = data.get('user_name')  # Ensure consistent key
    password = data.get('password')    # Use the correct key for password

    if not user_name or not password:
        return jsonify({'message': 'Username and password are required'}), 400

    cur = db.cursor()
    cur.execute("SELECT * FROM users WHERE user_name=%s", (user_name,))
    user = cur.fetchone()

    if user and check_password_hash(user[2], password):  # Ensure the password comparison is correct
        session['user_name'] = user_name
        cur.close()
        return jsonify({'message': 'Login successful'})
    cur.close()
    return jsonify({'message': 'Invalid username or password'}), 401

@app.route('/feedback', methods=['POST'])
def feedback():
    data = request.json
    name = data.get('name')
    email = data.get('email')
    message = data.get('message')

    try:
        with db.cursor() as cursor:
            sql = "INSERT INTO feedback (name, email, message) VALUES (%s, %s, %s)"
            cursor.execute(sql, (name, email, message))
            db.commit()

        return jsonify({"message": "Feedback received!"}), 200
    except Exception as e:
        print(f"Error: {e}")
        return jsonify({"error": "Error storing feedback"}), 500

@app.route('/find-recipes', methods=['POST'])
def find_recipes():
    try:
        if not request.is_json:
            return jsonify({"error": "Content-Type must be application/json."}), 415

        data = request.json
        ingredients = data.get("ingredients", [])
        diet = data.get("diet", "")

        if not ingredients:
            return jsonify({"error": "Ingredients list cannot be empty."}), 400

        ingredients_query = ",".join(ingredients)
        url = "https://api.spoonacular.com/recipes/complexSearch"
        params = {
            "apiKey": SPOONACULAR_API_KEY,
            "includeIngredients": ingredients_query,
            "diet": diet,
            "number": 10,
        }

        response = requests.get(url, params=params)

        if response.status_code != 200:
            return jsonify({"error": f"Spoonacular API error: {response.status_code} {response.text}"}), 500

        recipes_data = response.json().get("results", [])
        recipes = [{"id": recipe.get("id"), "title": recipe.get("title")} for recipe in recipes_data]

        return jsonify({"recipes": recipes})

    except Exception as e:
        print(f"Error occurred: {str(e)}")
        return jsonify({"error": f"An error occurred: {str(e)}"}), 500

@app.route('/recipe/<int:recipe_id>', methods=['GET'])
def get_recipe_details(recipe_id):
    url = f"https://api.spoonacular.com/recipes/{recipe_id}/information"
    params = {"apiKey": SPOONACULAR_API_KEY}
    response = requests.get(url, params=params)
   
    if response.status_code == 200:
        return jsonify(response.json())
    else:
        return jsonify({"error": f"Failed to fetch recipe details: {response.status_code}"}), 500

@app.route('/like-recipe', methods=['POST'])
def like_recipe():
    # Check if user is logged in
    if 'user_name' not in session:
        return jsonify({"message": "Please login to like recipes"}), 401

    data = request.get_json()
    recipe_id = data.get("recipe_id")
    recipe_title = data.get("recipe_title")

    if not recipe_id or not recipe_title:
        return jsonify({"message": "Recipe ID and title are required"}), 400

    user_name = session['user_name']
   
    # Fetch the user ID based on the logged-in username
    cur = db.cursor()
    cur.execute("SELECT id FROM users WHERE user_name = %s", (user_name,))
    user = cur.fetchone()
    if not user:
        cur.close()
        return jsonify({"message": "User not found"}), 404

    user_id = user[0]

    # Check if the recipe is already liked
    cur.execute("SELECT * FROM liked_recipes WHERE user_id = %s AND recipe_id = %s",
                (user_id, recipe_id))
    existing = cur.fetchone()

    try:
        if existing:
            # If already liked, remove it (unlike)
            cur.execute("DELETE FROM liked_recipes WHERE user_id = %s AND recipe_id = %s",
                        (user_id, recipe_id))
            db.commit()
            message = "Recipe unliked successfully!"
        else:
            # Otherwise, add it to liked_recipes
            cur.execute("INSERT INTO liked_recipes (user_id, recipe_id, recipe_title) VALUES (%s, %s, %s)",
                        (user_id, recipe_id, recipe_title))
            db.commit()
            message = "Recipe liked successfully!"

        cur.close()
        return jsonify({"message": message}), 201
    except Exception as e:
        print(f"Error: {e}")
        return jsonify({"error": "Error storing liked recipe"}), 500
@app.route('/get-liked-recipes/<user_name>', methods=['GET'])
def get_liked_recipes(user_name):
    if user_name in liked_recipes_db:
        return jsonify({"recipes": liked_recipes_db[user_name]}), 200
    return jsonify({"message": "No liked recipes found."}), 404


@retry(stop_max_attempt_number=3, wait_fixed=2000)
def fetch_recipes():
    response = requests.get(
        'https://api.spoonacular.com/recipes/complexSearch',
        params={
            'apiKey': 'YOUR_API_KEY',
            'includeIngredients': 'tomato',
            'diet': '',
            'number': 10
        },
        timeout=60
    )
    return response.json()

try:
    data = fetch_recipes()
    print(data)
except Exception as e:
    print(f"Failed to fetch recipes: {e}")
if __name__ == "__main__":
    app.run(debug=True)





app.css
body {
  margin: 0;
  font-family: Arial, sans-serif;
  /*background-image: url('/public/assets/smart-back.png'); /* Set your background image
  background-size: cover; /* Ensure the image covers the entire screen
  background-position: center; /* Center the background image
  background-repeat: no-repeat; /* Don't repeat the image
  height: 100vh; /* Full height
  display: flex;
  flex-direction: column;
  justify-content: space-between; /* To ensure the content is spaced properly */
  color: #333; /* Set text color for contrast */
  /* Remove background image */
  background: none;
  margin: 0;
  padding: 0;
  font-family: Arial, sans-serif;
  overflow-x: hidden; /* Prevent horizontal scroll */
}
/* Basic CSS for app layo*/
/* Remove background image */
body {
  background: none;
  margin: 0;
  padding: 0;
  font-family: Arial, sans-serif;
}
/* Remove background image */
/* Remove background image */
body {
  background: none;
  margin: 0;
  padding: 0;
  font-family: Arial, sans-serif;
}

.App {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
}

.dancing-icon {
  position: absolute;
  width: 40px;
  height: 40px;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  animation: dance 3s infinite ease-in-out;
}

/* Use Corrected Paths for Images */
.vegetable-1 {
  background-image: url('./assets/veg1.png'); /* Ensure the path is correct */
}

.vegetable-2 {
  background-image: url('./assets/veg2.png');
}

.vegetable-3 {
  background-image: url('./assets/veg3.png');
}

.vegetable-4 {
  background-image: url('./assets/veg4.png');
}

.vegetable-5 {
  background-image: url('./assets/veg5.png');
}
.vegetable-6 {
  background-image: url('./assets/veg1.png');
}
.vegetable-7 {
  background-image: url('./assets/veg2.png');
}
.vegetable-8 {
  background-image: url('./assets/veg3.png');
}
.vegetable-9 {
  background-image: url('./assets/veg4.png');
}
.vegetable-10 {
  background-image: url('./assets/veg5.png');
}

/* Random Positions for Each Vegetable */
.dancing-icon:nth-child(1) { top: 10%; left: 10%; }
.dancing-icon:nth-child(2) { top: 15%; left: 30%; }
.dancing-icon:nth-child(3) { top: 25%; left: 70%; }
.dancing-icon:nth-child(4) { top: 35%; left: 50%; }
.dancing-icon:nth-child(5) { top: 45%; left: 20%; }
.dancing-icon:nth-child(6) { top: 55%; left: 80%; }
.dancing-icon:nth-child(7) { top: 65%; left: 10%; }
.dancing-icon:nth-child(8) { top: 75%; left: 60%; }
.dancing-icon:nth-child(9) { top: 85%; left: 40%; }
.dancing-icon:nth-child(10) { top: 95%; left: 30%; }
.dancing-icon:nth-child(11) { top: 10%; left: 80%; }
.dancing-icon:nth-child(12) { top: 20%; left: 40%; }
.dancing-icon:nth-child(13) { top: 30%; left: 60%; }
.dancing-icon:nth-child(14) { top: 40%; left: 10%; }
.dancing-icon:nth-child(15) { top: 50%; left: 70%; }
.dancing-icon:nth-child(16) { top: 60%; left: 50%; }
.dancing-icon:nth-child(17) { top: 70%; left: 20%; }
.dancing-icon:nth-child(18) { top: 80%; left: 80%; }
.dancing-icon:nth-child(19) { top: 90%; left: 30%; }
.dancing-icon:nth-child(20) { top: 100%; left: 50%; }

/* Animation for Dancing Effect */
@keyframes dance {
  0%, 100% {
    transform: translateY(0) rotate(0deg);
  }
  25% {
    transform: translateY(-20px) rotate(10deg);
  }
  50% {
    transform: translateY(0) rotate(-10deg);
  }
  75% {
    transform: translateY(20px) rotate(5deg);
  }
}

.App {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.nav-container {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 20px;
  background-color: rgba(0, 0, 0, 0.5); /* Slight transparency for background */
}

.sign-up-container {
  flex-grow: 1;
}

.sign-up-button {
  background-color: #e60000;
  color: white;
  font-size: 16px;
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}

.menu {
  list-style: none;
  display: flex;
  gap: 20px;
}

.menu li {
  display: flex;
}

.menu a {
  color: white;
  text-decoration: none;
  font-size: 18px;
}

.App-header {
  padding: 50px;
  color:black;
}

footer {
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 30px;
  margin-top: auto;
}

.footer-content {
  max-width: 1200px;
  margin: 0 auto;
  text-align: center;
}

.footer-links a {
  color: white;
  margin-right: 20px;
  text-decoration: none;
}

.footer-store img {
  width: 100px;
  margin: 10px;
}

.footer-social a {
  color: white;
  margin-right: 15px;
  text-decoration: none;
}

.donate-button {
  padding: 10px 20px;
  background-color: #e60000;
  color: white;
  border: none;
  font-size: 16px;
  cursor: pointer;
  margin-top: 20px;
}

.App-header {
  text-align: center;
  padding: 20px;
  color: black;
}

h1 {
  font-size: 3rem;
  margin-bottom: 10px;
}

main {
  padding: 20px;
}

.recipe-form-container {
  background: rgba(177, 186, 176, 0.7);
  color: #333;
  border-radius: 10px;
  padding: 20px;
  width: 80%;
  margin: 20px auto;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.form-group {
  margin-bottom: 15px;
}

input, select {
  width: 100%;
  padding: 10px;
  margin-top: 5px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

button.fetch-button {
  background: #ff5e62;
  color: #fff;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 1rem;
}

button.fetch-button:hover {
  background: #ff9966;
}

.recipe-list {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  justify-content: center;
}

.recipe-card {
  background: #fff;
  color: #333;
  border-radius: 10px;
  width: 200px;
  padding: 15px;
  text-align: center;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  position: relative;
}

.recipe-card img {
  width: 100%;
  border-radius: 10px;
}

footer {
  background-color: #f1f1f1;
  color: #333;
  padding: 20px;
  text-align: center;
  font-family: Arial, sans-serif;
}

.footer-container {
  max-width: 1200px;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
}

.footer-content {
  flex: 1 1 300px;
  text-align: center;
}

.footer-links {
  display: flex;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
}

.footer-links a {
  color: #ff5e62;
  text-decoration: none;
  font-size: 14px;
}

.footer-links a:hover {
  text-decoration: underline;
}

.footer-social {
  display: flex;
  justify-content: center;
  gap: 15px;
}

.footer-social a {
  color: #555;
  font-size: 1.2em;
  transition: color 0.3s;
}

.footer-social a:hover {
  color: #ff5e62;
}

.footer-store {
  display: flex;
  justify-content: center;
  gap: 30px;
}

.footer-store img {
  width: 100px;
  height: auto;
}

.donate-button {
  background-color: #4caf50;
  color: white;
  border: none;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
  border-radius: 5px;
}

.donate-button:hover {
  background-color: #45a049;
}

@media (max-width: 768px) {
  .footer-content {
    flex-direction: column;
  }
}

.login-form {
  max-width: 400px;
  margin: auto;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(186, 178, 178, 0.5);
}

label {
  display: block;
  margin-bottom: 5px;
}

input {
  width: 100%;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.error-message {
  color: red;
  font-size: 0.9em;
}

.login-button {
  background-color: #28a745;
  color: white;
  padding: 10px 15px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.login-button:hover {
  background-color: #218838;
}

nav ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  justify-content: flex-end;
  background-color: #333;
}
/*
nav ul li {
  margin: 0 15px;
}

nav ul li a {
  color: white;
  text-decoration: none;
  padding: 10px 15px;
  font-size: 16px;
}

nav ul li a:hover {
  background-color: #555;
  border-radius: 5px;
}
*/
.recipe-details {
  padding: 20px;
  border: 1px solid #ddd;
  background-color: #fff;
  position: fixed;
  top: 10px;
  left: 30%;
  width: 40%;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  z-index: 10;
}

.recipe-details h2 {
  margin-bottom: 10px;
}

.recipe-details img {
  width: 100%;
  height: auto;
  margin-bottom: 50px;
}

.recipe-details button {
  padding: 10px;
  background: #ff5a5f;
  color: #fff;
  border: none;
  cursor: pointer;
}

nav {
  background-color: #333;
}

.menu {
  list-style-type: none;
  margin: 0;
  padding: 0;
  display: inline;
  justify-content: flex-end;
}

.menu li {
  margin: 0 20px;
 display:flex;
}

.menu li a {
  color: white;
  text-decoration: none;
  font-size: 1.1rem;
  padding: 15px 20px;
  display: block;
  transition: background-color 0.3s, color 0.3s;
  border-radius: 5px;
}
.menu li a:hover {
  background-color: #ff5e62;
  color: #fff;
}

.menu li a.active {
  background-color: #ff9966;
}
@keyframes bounce {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-10px);
  }
  60% {
    transform: translateY(-5px);
  }
}

.like-icon {
  position: absolute;
  top: 10px;
  left: 10px;
  font-size: 24px;
  cursor: pointer;
}
.nav-container {
  display: flex;
  margin-left: 0;;
  align-items: center;
}
.nav-container .menu {
  list-style-type: none;
  display: flex; /* Align menu items in a row*/
  padding: 0;
  margin: 0;
  width:100%;
  justify-content: flex-end;
}

.nav-container .menu li {
  margin-right: 15px;  /*Adjust spacing between menu items */
}

.nav-container .menu li:last-child {
  margin-left: 0; /* Remove margin from the last item*/
}


.sign-up-button {
  margin-right: auto; /* Moves the button to the leftmost position */
  padding: 10px 20px;
  background-color: #ff5733;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.user-greeting {
  margin-right: auto;
  font-size: 1rem;
  font-weight: bold;
  color: #333;
  padding-right: 15px;
}

/* Style for the sign-up and donate buttons */

/* Button styles for primary and secondary actions */
.button.primary {
  background-color: #4caf50;
  color: white;
}

.button.secondary {
  background-color: #2196f3;
  color: white;
}

.button.primary:hover,
.button.secondary:hover {
  opacity: 0.8;
}

/* Welcome message styling */
.welcome-message {
  font-size: 2.2rem;
  font-weight: 500;
  color: #444;
  top: 20px;
}
.login-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100%;
  position: relative;
}

.login-card {
  background: rgba(179, 165, 173, 0.1);
  border-radius: 8px;
  padding: 60px 40px 40px;
  width: 400px;
  box-shadow: 0 2px 10px rgba(169, 161, 161, 0.1);
  text-align: center;
  position: relative;
}

.login-title {
  font-size: 28px;
  margin-bottom: 10px;
  font-weight: bold;
}

.login-subtitle {
  font-size: 16px;
  color: #6b6b6b;
  margin-bottom: 30px;
}

.form-group {
  margin-bottom: 20px;
  text-align: left;
}

.form-group label {
  font-size: 14px;
  margin-bottom: 5px;
  display: block;
}

.input-field {
  width: 100%;
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
}

.options {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}
.button {
  width: 100%;
  padding: 12px;
  font-size: 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  margin-bottom: 10px;
}

.button.primary {
  background-color: #6c63ff;
  color: #ffffff;
}

.button.google {
  background-color: #ffffff;
  color: #333;
  border: 1px solid #ddd;
}

.signup-link {
  font-size: 14px;
}

.signup-link a {
  color: #6c63ff;
  text-decoration: none;
}

.signup-link a:hover {
  text-decoration: underline;
}

/* Custom styling for the sign-up button */
.sign-up-button {
  background-color: #ff7043;
  color: #ffffff;
  font-size: 16px;
  padding: 12px 20px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.sign-up-button:hover {
  background-color: #ff5722;
}
@keyframes jumpy {
  0%, 100% {
    transform: translateY(0);
  }
  80% {
    transform: translateY(-10px);
  }
}

.user-greeting {
  font-size: 1.2rem;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  animation: jumpy 2.5s infinite;
  font-weight: bold;
  color: orangered;
}
.logo-top-right {
  display: flex;
  align-items: center;
  position: absolute;
  top: 30px;
  left: 50px;
}

.logo {
  height: 40px;
  margin-right: 8px;
}

.logo-name {
  font-size: 1.5rem;
  font-weight: bold;
  color: #4CAF50;
}


login page.js

import React, { useState } from 'react';
import axios from 'axios';
import './App.css';

const LoginPage = ({ setUserName }) => {
  const [userName, setUserNameInput] = useState('');
  const [password, setPassword] = useState('');
  const [showPassword, setShowPassword] = useState(false);

  const validateInput = () => {
    if (!userName || !password) {
      alert('Please enter a valid username and password.');
      setUserNameInput('');
      setPassword('');
      return false;
    }
    return true;
  };

  const handleSignup = async () => {
    if (!validateInput()) return;
    try {
      const response = await axios.post('http://localhost:5000/signup', {
        user_name: userName,
        password: password,
      });
      alert(response.data.message);
      if (response.data.message === 'Signup successful!') {
        setUserName(userName);
        setUserNameInput('');
        setPassword('');
        window.location.href = '/';
      }
    } catch (error) {
      handleError(error);
    }
  };

  const handleLogin = async () => {
    if (!validateInput()) return;
    try {
      const response = await axios.post('http://localhost:5000/login', {
        user_name: userName,
        password: password,
      });
      alert(response.data.message);
      if (response.data.message === 'Login successful') {
        setUserName(userName);
        setUserNameInput('');
        setPassword('');
        window.location.href = '/';
      }
    } catch (error) {
      handleError(error);
    }
  };

  const handleError = (error) => {
    if (error.response && error.response.data) {
      alert(error.response.data.message);
    } else {
      alert('Network error: Could not connect to the server. Please check if the server is running.');
    }
    setUserNameInput('');
    setPassword('');
  };

  return (
    <div className="login-container">
      <div className="login-card">
        <h1 className="login-title">Welcome to Recipe Finder</h1>
        <p className="login-subtitle">Please sign up or log in to continue</p>
        <div className="form-group">
          <label>Username</label>
          <input
            type="text"
            placeholder="Username"
            value={userName}
            onChange={(e) => setUserNameInput(e.target.value)}
            className="input-field"
          />
        </div>
        <div className="form-group">
          <label>Password</label>
          <input
            type={showPassword ? 'text' : 'password'}
            placeholder="Password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            className="input-field"
          />
        </div>
        <div className="options">
          <label>
            <input
              type="checkbox"
              checked={showPassword}
              onChange={() => setShowPassword(!showPassword)}
            />
            Show Password
          </label>
        </div>
        <div className="button-group">
          <button onClick={handleSignup} className="button primary">Sign up</button>
          <button onClick={handleLogin} className="button secondary">Sign in</button>
        </div>
      </div>
    </div>
  );
};

export default LoginPage;

app.js

import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import "./App.css";
import RecipeForm from "./RecipeForm";
import FeedbackForm from "./FeedbackForm";
import GalleryPage from "./GalleryPage";
import AboutPage from "./AboutPage";
import ContactPage from "./ContactPage";
import LoginPage from "./LoginPage";

function HomePage({ likedRecipes, setLikedRecipes, userName }) {
  return (
    <div>
      {userName && <p className="welcome-message">Hi, {userName}!</p>}
      <RecipeForm likedRecipes={likedRecipes} setLikedRecipes={setLikedRecipes} />
    </div>
  );
}

function FamousRecipesPage() {
  return <h2>Famous Recipes</h2>;
}

function App() {
  const [likedRecipes, setLikedRecipes] = useState([]);
  const [userName, setUserName] = useState(localStorage.getItem("userName") || null);

  useEffect(() => {
    if (userName) {
      localStorage.setItem("userName", userName);
    }
  }, [userName]);

  const handleLogout = () => {
    localStorage.removeItem("userName");
    setUserName(null);
    window.location.href = "/";
  };

  return (
    <Router>
      <div className="App">
        <div className="dancing-icons-container">
          {Array.from({ length: 20 }, (_, i) => (
            <div key={i} className={`dancing-icon vegetable-${i % 5 + 1}`}></div>
          ))}
        </div>

        <nav className="nav-container">
          <ul className="menu">
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About Us</Link></li>
            <li><Link to="/famous-recipes">Famous Recipes</Link></li>
            <li><Link to="/gallery">Gallery</Link></li>
            <li><Link to="/feedback">Feedback</Link></li>
            <li><Link to="/contact">Contact Us</Link></li>
            {userName ? (
              <>
                <li>
                  <button onClick={handleLogout} className="logout-button">Logout</button>
                </li>
              </>
            ) : (
              <li>
                <Link to="/login">
                  <button className="sign-up-button">Sign Up/Sign in</button>
                </Link>
              </li>
            )}
          </ul>
        </nav>

        <header className="App-header">
          <h1 className="animate__animated animate__bounce">Recipe Finder</h1>
          <div className="logo-top-right">
            <img src="assets/logo.png" alt="TasteBuddy Logo" className="logo" />
            <h1 className="logo-name">TasteBuddy</h1>
          </div>
          <p>Enter ingredients and preferences to find amazing recipes!</p>
        </header>
        <main>
          <Routes>
            <Route path="/" element={<HomePage likedRecipes={likedRecipes} setLikedRecipes={setLikedRecipes} userName={userName} />} />
            <Route path="/about" element={<AboutPage />} />
            <Route path="/famous-recipes" element={<FamousRecipesPage />} />
            <Route path="/gallery" element={<GalleryPage likedRecipes={likedRecipes} />} />
            <Route path="/feedback" element={<FeedbackForm />} />
            <Route path="/contact" element={<ContactPage />} />
            <Route path="/login" element={<LoginPage setUserName={setUserName} />} />
          </Routes>
        </main>
        <footer>
          <div className="footer-content">
            <div className="footer-links">
              <Link to="/about">About</Link>
              <Link to="/">Press</Link>
              <Link to="/">Terms & Privacy</Link>
              <Link to="/">DMCA</Link>
              <Link to="/">Contact & Imprint</Link>
            </div>
            <div className="footer-store">
              <a href="https://play.google.com" target="_blank" rel="noopener noreferrer">
                <img src="assets/but-play.png" alt="Google Play" />
              </a>
              <a href="https://www.apple.com/app-store/" target="_blank" rel="noopener noreferrer">
                <img src="assets/but-app.png" alt="App Store" />
              </a>
            </div>
            <div className="footer-social">
              <a href="https://www.facebook.com" target="_blank" rel="noopener noreferrer">Facebook</a>
              <a href="https://www.twitter.com" target="_blank" rel="noopener noreferrer">Twitter</a>
              <a href="https://www.pinterest.com" target="_blank" rel="noopener noreferrer">Pinterest</a>
            </div>
            <p>&copy; 2024 Recipe Finder. All rights reserved.</p>
            <button className="donate-button">Donate</button>
          </div>
        </footer>
      </div>
    </Router>
  );
}

export default App






recipedetailse.js

import React from 'react';
import './RecipeDetails.css'; // Ensure the updated styles are used

const RecipeDetails = ({ recipe, onClose }) => {
  if (!recipe) return null;

  return (
    <div className="overlay">
      <div className="recipe-details">
        <h2>{recipe.title}</h2>
        <div className="fixed-image">
          <img src={recipe.image} alt={recipe.title} />
        </div>
        <div className="details-scrollable">
          <p><strong>Instructions:</strong> {recipe.instructions || 'No instructions available.'}</p>
          <p><strong>Ready in:</strong> {recipe.readyInMinutes} minutes</p>
          <p><strong>Servings:</strong> {recipe.servings}</p>
          <p><strong>Dietary Information:</strong> {recipe.diets?.join(', ') || 'Not specified'}</p>
          <p><strong>Cuisines:</strong> {recipe.cuisines?.join(', ') || 'Not specified'}</p>
          <p><strong>Health Score:</strong> {recipe.healthScore || 'Not available'}</p>
          <p><strong>Intolerances:</strong> {recipe.intolerances?.join(', ') || 'Not specified'}</p>
          <p><strong>Ingredients:</strong></p>
          <ul>
            {recipe.ingredients?.map((ingredient, index) => (
              <li key={index}>{ingredient.name || ingredient}</li>
            )) || <li>No ingredients available.</li>}
          </ul>
        </div>
        <button onClick={onClose}>Close</button>
      </div>
    </div>
  );
};

export default RecipeDetails;

recipedetailse.css

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.6); /* Darken background */
  z-index: 1000;
  display: flex;
  justify-content: center;
  align-items: center;
}

.recipe-details {
  background-color: #fff;
  padding: 20px;
  border-radius: 10px;
  width: 80%;
  max-width: 600px;
  max-height: 80%;
  overflow-y: auto;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.fixed-image img {
  width: 100%;
  max-height: 300px;
  object-fit: cover;
}

button {
  margin-top: 10px;
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

button:hover {
  background-color: #0056b3;
}

App.js

import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import "./App.css";
import RecipeForm from "./RecipeForm";
import FeedbackForm from "./FeedbackForm";
import GalleryPage from "./GalleryPage";
import AboutPage from "./AboutPage";
import ContactPage from "./ContactPage";
import LoginPage from "./LoginPage";
import TicTacToe from "./Game"; // Import the Tic Tac Toe game component

function HomePage({ likedRecipes, setLikedRecipes, userName }) {
  return (
    <div>
      {userName && <p className="welcome-message">Hi, {userName}!</p>}
      <RecipeForm likedRecipes={likedRecipes} setLikedRecipes={setLikedRecipes} />
    </div>
  );
}

/*function FamousRecipesPage() {
  return <h2>Famous Recipes</h2>;
}*/

function App() {
  const [likedRecipes, setLikedRecipes] = useState([]);
  const [userName, setUserName] = useState(localStorage.getItem("userName") || null);

  useEffect(() => {
    if (userName) {
      localStorage.setItem("userName", userName);
    }
  }, [userName]);

  const handleLogout = () => {
    localStorage.removeItem("userName");
    setUserName(null);
    window.location.href = "/"; // Redirect to home page after logout
  };

  return (
    <Router>
      <div className="App">
      <div className="dancing-icons-container">
          {Array.from({ length: 20 }, (_, i) => (
            <div key={i} className={`dancing-icon vegetable-${i % 5 + 1}`}></div>
          ))}
        </div>
        <nav className="nav-container">
          <ul className="menu">
            <ul className="menu_1">
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About Us</Link></li>
            <li><Link to="/contact">Contact Us</Link></li>

            {/* Show these menu items ONLY after login */}
            {userName && (
              <>
                <li><Link to="/gallery">Gallery</Link></li>
                <li><Link to="/FeedbackForm">FeedbackForm</Link></li>
                <li><Link to="/game">Play Game</Link></li>
              </>
            )}

            {/* Show Login / Sign Up only if the user is NOT logged in */}
            {!userName ?
              <li>
                <Link to="/login">
                  <button className="sign-up-button">Sign Up/Sign in</button>
                </Link>
              </li>
             : (
              <li>
                <button onClick={handleLogout} className="logout-button">Logout</button>
              </li>
            )}
          </ul>
          </ul>
        </nav>

        <header className="App-header">
          <div className="logo-top-right">
            <img src="assets/logo.png" alt="TasteBuddy Logo" className="logo" />
            <h1 className="logo-name">TasteBuddy</h1>
          </div>
        </header>

        <main>
          <Routes>
            <Route path="/" element={<HomePage likedRecipes={likedRecipes} setLikedRecipes={setLikedRecipes} userName={userName} />} />
            <Route path="/about" element={<AboutPage />} />
            <Route path="/contact" element={<ContactPage />} />
            <Route path="/login" element={<LoginPage setUserName={setUserName} />} />

            {/* Protect Gallery & Game routes - Only show if logged in */}
            {userName && <Route path="/gallery" element={<GalleryPage likedRecipes={likedRecipes} />} />}
            {userName && <Route path="/FeedbackForm"element={<FeedbackForm />}/>}
            {userName && <Route path="/game" element={<TicTacToe />} />}
          </Routes>
        </main>

        <footer>
          <div className="footer-content">
            <div className="footer-links">
              <Link to="/about">About</Link>
              <Link to="/">Press</Link>
              <Link to="/">Terms & Privacy</Link>
              <Link to="/">DMCA</Link>
              <Link to="/">Contact & Imprint</Link>
            </div>
            <div className="footer-store">
              <a href="https://play.google.com" target="_blank" rel="noopener noreferrer">
                <img src="assets/but-play.png" alt="Google Play" />
              </a>
              <a href="https://www.apple.com/app-store/" target="_blank" rel="noopener noreferrer">
                <img src="assets/but-app.png" alt="App Store" />
              </a>
            </div>
            <div className="footer-social">
              <a href="https://www.facebook.com" target="_blank" rel="noopener noreferrer">Facebook</a>
              <a href="https://www.twitter.com" target="_blank" rel="noopener noreferrer">Twitter</a>
              <a href="https://www.pinterest.com" target="_blank" rel="noopener noreferrer">Pinterest</a>
            </div>
            <p>&copy; 2024 Recipe Finder. All rights reserved.</p>
            <button className="donate-button">Donate</button>
          </div>
        </footer>
      </div>
    </Router>
  );
}

export default App;


Comments

Popular posts from this blog

login code