1. Home
  2. Vegas Mobile App
  3. Frontend
  4. Project Setup

Project Setup

  1. First, create a new React project:
npm create vite@latest vegas-mobile-app -- --template react
cd vegas-mobile-app
  1. Install required dependencies:
npm install react-router-dom lucide-react tailwindcss postcss autoprefixer
  1. Initialize Tailwind CSS:
npx tailwindcss init -p
  1. Create the project structure:
mkdir src/components src/pages

Your project structure should look like this:

vegas-mobile-app/
├── public/
├── src/
   ├── components/
      ├── Header.jsx
      └── Footer.jsx
   ├── pages/
      ├── Login.jsx
      └── VIPPage.jsx
   ├── App.jsx
   ├── index.js
   └── index.css
├── package.json
└── tailwind.config.js
  1. Replace the content of tailwind.config.js with:
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        primary: '#011641',
        secondary: '#0a1f5c',
        accent: {
          DEFAULT: '#f0d07e',
          light: '#ffd55f',
        },
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
}
  1. Update src/index.css:
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
  .no-scrollbar::-webkit-scrollbar {
    display: none;
  }
  .no-scrollbar {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #011641;
}

Create all the component files as provided in the previous responses:

  • Copy the code for Header.jsx into src/components/Header.jsx
  • Copy the code for Footer.jsx into src/components/Footer.jsx
  • Copy the code for Login.jsx into src/pages/Login.jsx
  • Copy the code for VIPPage.jsx into src/pages/VIPPage.jsx
import React from "react"
import { ArrowLeft, Bell } from "lucide-react"

const Header = ({ title, showBack = false, showNotification = false }) => {
  return (
    <header className="bg-[#011641] p-4 flex justify-between items-center">
      <div className="flex items-center">
        {showBack && (
          <button className="mr-4">
            <ArrowLeft className="w-6 h-6 text-[#f0d07e]" />
          </button>
        )}
        <h1 className="text-[#f0d07e] text-xl font-bold">{title}</h1>
      </div>
      {showNotification && (
        <button>
          <Bell className="w-6 h-6 text-[#f0d07e]" />
        </button>
      )}
    </header>
  )
}

export default Header

import React from "react"
import { Home, Gift, Clock, User } from "lucide-react"

const Footer = () => {
  return (
    <footer className="bg-[#011641] border-t border-[#0a1f5c] fixed bottom-0 left-0 right-0">
      <nav className="flex justify-around p-4">
        <a href="/" className="flex flex-col items-center text-white/80 hover:text-[#ffd55f]">
          <Home className="h-6 w-6" />
          <span className="text-xs mt-1">Home</span>
        </a>
        <a href="/promotion" className="flex flex-col items-center text-white/80 hover:text-[#ffd55f]">
          <Gift className="h-6 w-6" />
          <span className="text-xs mt-1">Promotion</span>
        </a>
        <a href="/history" className="flex flex-col items-center text-white/80 hover:text-[#ffd55f]">
          <Clock className="h-6 w-6" />
          <span className="text-xs mt-1">History</span>
        </a>
        <a href="/vip" className="flex flex-col items-center text-[#ffd55f]">
          <User className="h-6 w-6" />
          <span className="text-xs mt-1">VIP</span>
        </a>
      </nav>
    </footer>
  )
}

export default Footer

import React from "react"
import Header from "../components/Header"
import Footer from "../components/Footer"

const Login = () => {
  return (
    <div className="min-h-screen bg-[#011641] text-white flex flex-col">
      <Header title="Login" />
      <main className="flex-1 p-4 flex flex-col justify-center">
        <div className="mb-8 text-center">
          <img src="/placeholder.svg?height=60&width=200" alt="LASVEGAS138 Logo" className="w-48 h-14 mx-auto mb-4" />
          <h2 className="text-2xl font-bold text-[#f0d07e]">Welcome Back</h2>
        </div>
        <form className="space-y-4">
          <div>
            <label htmlFor="username" className="block text-sm font-medium text-gray-300 mb-1">
              Username
            </label>
            <input
              type="text"
              id="username"
              className="w-full px-3 py-2 bg-[#0a1f5c] rounded-md text-white placeholder-gray-400"
              placeholder="Enter your username"
            />
          </div>
          <div>
            <label htmlFor="password" className="block text-sm font-medium text-gray-300 mb-1">
              Password
            </label>
            <input
              type="password"
              id="password"
              className="w-full px-3 py-2 bg-[#0a1f5c] rounded-md text-white placeholder-gray-400"
              placeholder="Enter your password"
            />
          </div>
          <button
            type="submit"
            className="w-full py-2 px-4 bg-gradient-to-r from-[#f0d07e] to-[#f2c36b] text-[#011641] font-bold rounded-md hover:opacity-90 transition-opacity"
          >
            Login
          </button>
        </form>
        <div className="mt-4 text-center">
          <a href="#" className="text-[#f0d07e] hover:underline">
            Forgot Password?
          </a>
        </div>
      </main>
      <Footer />
    </div>
  )
}

export default Login

import React, { useState } from "react"
import Header from "../components/Header"
import Footer from "../components/Footer"

const VIP_DATA = {
  Bronze: {
    color: "#CD7F32",
    benefits: {
      "Designated Account Manager": "Yes",
      "Weekly Cashback Bonus": "-",
      "Daily Rebate Bonus(Min Lose 100)": "4.00% & MAX CAP 300",
      "Special Birthday Bonus": "48",
      "Special Birthday Gift": "-",
      "Minimum Deposit Within 1 Month": "RM 3,000",
      "Membership Renewal": "Lifetime",
    },
  },
  Silver: {
    color: "#C0C0C0",
    benefits: {
      "Designated Account Manager": "Yes",
      "Weekly Cashback Bonus": "0.3%",
      "Daily Rebate Bonus(Min Lose 100)": "4.50% & MAX CAP 500",
      "Special Birthday Bonus": "88",
      "Special Birthday Gift": "Silver Gift",
      "Minimum Deposit Within 1 Month": "RM 8,000",
      "Membership Renewal": "Lifetime",
    },
  },
  Gold: {
    color: "#FFD700",
    benefits: {
      "Designated Account Manager": "Yes",
      "Weekly Cashback Bonus": "0.5%",
      "Daily Rebate Bonus(Min Lose 100)": "5.00% & MAX CAP 800",
      "Special Birthday Bonus": "188",
      "Special Birthday Gift": "Gold Gift",
      "Minimum Deposit Within 1 Month": "RM 18,000",
      "Membership Renewal": "Lifetime",
    },
  },
  Platinum: {
    color: "#E5E4E2",
    benefits: {
      "Designated Account Manager": "Yes",
      "Weekly Cashback Bonus": "0.8%",
      "Daily Rebate Bonus(Min Lose 100)": "5.50% & MAX CAP 1,200",
      "Special Birthday Bonus": "288",
      "Special Birthday Gift": "Platinum Gift",
      "Minimum Deposit Within 1 Month": "RM 38,000",
      "Membership Renewal": "Lifetime",
    },
  },
  Diamond: {
    color: "#B9F2FF",
    benefits: {
      "Designated Account Manager": "Yes",
      "Weekly Cashback Bonus": "1.0%",
      "Daily Rebate Bonus(Min Lose 100)": "6.00% & MAX CAP 1,800",
      "Special Birthday Bonus": "388",
      "Special Birthday Gift": "Diamond Gift",
      "Minimum Deposit Within 1 Month": "RM 88,000",
      "Membership Renewal": "Lifetime",
    },
  },
  Royal: {
    color: "#FFD700",
    benefits: {
      "Designated Account Manager": "Yes",
      "Weekly Cashback Bonus": "1.5%",
      "Daily Rebate Bonus(Min Lose 100)": "6.50% & MAX CAP 2,500",
      "Special Birthday Bonus": "588",
      "Special Birthday Gift": "Royal Gift",
      "Minimum Deposit Within 1 Month": "RM 188,000",
      "Membership Renewal": "Lifetime",
    },
  },
}

const VIPBadge = ({ level, isActive }) => (
  <div className={`flex flex-col items-center ${isActive ? "" : "opacity-50"}`}>
    <div className="w-16 h-16 rounded-full bg-gradient-to-b from-[#f0d07e] to-[#f2c36b] p-0.5 mb-2">
      <div
        className="w-full h-full rounded-full bg-[#011641] flex items-center justify-center"
        style={{
          background: `radial-gradient(circle at center, ${VIP_DATA[level].color}33 0%, #011641 70%)`,
        }}
      >
        <img src="/placeholder.svg?height=48&width=48" alt={`${level} Badge`} className="w-12 h-12 object-contain" />
      </div>
    </div>
    <span className="text-xs text-center">{level}</span>
  </div>
)

const VIPPage = () => {
  const [activeTab, setActiveTab] = useState("Bronze")

  return (
    <div className="min-h-screen bg-[#011641] text-white flex flex-col pb-20">
      <Header title="VIP" showBack showNotification />

      {/* VIP Title Section */}
      <div className="text-center my-6">
        <h1 className="text-3xl font-bold text-[#f0d07e]">VIP</h1>
        <p className="text-gray-400 mt-2">
          See your progress, unlock badges,
          <br />
          and deposit to reach the next level!
        </p>
      </div>

      {/* VIP Badges */}
      <div className="px-4 mb-8">
        <h2 className="text-xl font-bold text-[#f0d07e] mb-4">Current Rank Badge</h2>
        <div className="grid grid-cols-3 gap-4">
          {Object.keys(VIP_DATA).map((level) => (
            <VIPBadge key={level} level={level} isActive={activeTab === level} onClick={() => setActiveTab(level)} />
          ))}
        </div>
      </div>

      {/* VIP Level Tabs */}
      <div className="px-4 mb-4">
        <div className="flex overflow-x-auto space-x-2 pb-2 no-scrollbar">
          {Object.keys(VIP_DATA).map((level) => (
            <button
              key={level}
              className={`px-4 py-2 rounded-full text-sm font-medium whitespace-nowrap transition-colors ${
                activeTab === level ? "bg-[#f0d07e] text-[#011641]" : "bg-[#0a1f5c] text-white"
              }`}
              onClick={() => setActiveTab(level)}
            >
              {level}
            </button>
          ))}
        </div>
      </div>

      {/* VIP Benefits */}
      <div className="px-4 mb-20">
        <h2 className="text-xl font-bold text-[#f0d07e] mb-4">VIP Benefits</h2>
        <div className="space-y-2">
          {Object.entries(VIP_DATA[activeTab].benefits).map(([benefit, value]) => (
            <div key={benefit} className="flex justify-between py-3 px-4 bg-[#0a1f5c] rounded-lg">
              <span className="text-sm text-gray-200">{benefit}</span>
              <span className={`text-sm ${value === "Yes" ? "text-[#f0d07e]" : "text-gray-200"}`}>{value}</span>
            </div>
          ))}
        </div>
      </div>

      <Footer />
    </div>
  )
}

export default VIPPage

  1. Update src/App.jsx:
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Login from './pages/Login';
import VIPPage from './pages/VIPPage';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Login />} />
        <Route path="/vip" element={<VIPPage />} />
      </Routes>
    </Router>
  );
}

export default App;
  1. Update src/index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
  1. Add placeholder images:
    Create a public folder and add placeholder images for:
  • Logo
  • VIP badges
  • Navigation icons
  1. Start the development server:
npm start

How can we help?