diff --git a/api/live_station_handler.php b/api/live_station_handler.php new file mode 100644 index 0000000..5d45602 --- /dev/null +++ b/api/live_station_handler.php @@ -0,0 +1,17 @@ + 'Station code is required.']); + exit; +} + +$api = new RailApi(); +$response = $api->getLiveStation($stationCode, $hours); + +echo json_encode($response); +?> \ No newline at end of file diff --git a/api/live_train_status_handler.php b/api/live_train_status_handler.php new file mode 100644 index 0000000..3b42c3c --- /dev/null +++ b/api/live_train_status_handler.php @@ -0,0 +1,48 @@ + 'Train number and date are required.']); + exit; +} + +// For demo purposes, we will return a mock response that includes a known station code. +// In a real scenario, this would come from the RailApi call. +$mockApiResponse = [ + 'ResponseCode' => 200, + 'TrainName' => 'SAMPARK KRANTI', + 'TrainNo' => '12649', + 'Position' => 'Arrived at KSR BENGALURU (SBC)', + 'CurrentStation' => ['StationCode' => 'SBC', 'StationName' => 'KSR BENGALURU'], + 'Route' => [ + ['StationCode' => 'NDLS', 'StationName' => 'NEW DELHI', 'ScheduleArrival' => '20:00', 'ActualArrival' => '20:00', 'ScheduleDeparture' => '20:15', 'ActualDeparture' => '20:15', 'IsCurrentStation' => false], + ['StationCode' => 'SBC', 'StationName' => 'KSR BENGALURU', 'ScheduleArrival' => '06:30', 'ActualArrival' => '06:30', 'ScheduleDeparture' => '-', 'ActualDeparture' => '-', 'IsCurrentStation' => true] + ] +]; + +if ($mockApiResponse['ResponseCode'] == 200) { + $currentStationCode = $mockApiResponse['CurrentStation']['StationCode']; + + try { + $pdo = db(); + $stmt = $pdo->prepare("SELECT latitude, longitude FROM stations WHERE station_code = ?"); + $stmt->execute([$currentStationCode]); + $coords = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($coords) { + $mockApiResponse['CurrentStation']['latitude'] = $coords['latitude']; + $mockApiResponse['CurrentStation']['longitude'] = $coords['longitude']; + } + } catch (PDOException $e) { + // Could not fetch coordinates, but we can still return the rest of the data. + } +} + +echo json_encode($mockApiResponse); + +?> \ No newline at end of file diff --git a/api/pnr_handler.php b/api/pnr_handler.php new file mode 100644 index 0000000..08ddcd7 --- /dev/null +++ b/api/pnr_handler.php @@ -0,0 +1,16 @@ + 'PNR number is required.']); + exit; +} + +$api = new RailApi(); +$response = $api->checkPnrStatus($pnrNumber); + +echo json_encode($response); +?> \ No newline at end of file diff --git a/api/rail_api.php b/api/rail_api.php new file mode 100644 index 0000000..f4ee726 --- /dev/null +++ b/api/rail_api.php @@ -0,0 +1,46 @@ +apiKey = getenv('RAIL_API_KEY') ?: 'YOUR_API_KEY_HERE'; + } + + private function makeRequest($endpoint) { + $url = $this->baseUrl . $endpoint; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $response = curl_exec($ch); + curl_close($ch); + + return json_decode($response, true); + } + + public function checkPnrStatus($pnrNumber) { + $endpoint = "PNRCheck/apikey/{$this->apiKey}/PNRNumber/{$pnrNumber}/"; + return $this->makeRequest($endpoint); + } + + public function getLiveTrainStatus($trainNumber, $date) { + $endpoint = "livetrainstatus/apikey/{$this->apiKey}/trainnumber/{$trainNumber}/date/{$date}/"; + return $this->makeRequest($endpoint); + } + + public function getLiveStation($stationCode, $hours) { + $endpoint = "LiveStation/apikey/{$this->apiKey}/StationCode/{$stationCode}/hours/{$hours}/"; + return $this->makeRequest($endpoint); + } + + public function searchTrains($from, $to, $date) { + // Note: The API docs you provided don't have a direct train search endpoint like this. + // This is a placeholder for a possible endpoint or a feature that might need a different API. + // For now, it will return a mock response. + return ['error' => 'Train search functionality is not available in the provided API endpoints.']; + } +} +?> \ No newline at end of file diff --git a/api/train_search_handler.php b/api/train_search_handler.php new file mode 100644 index 0000000..4c0096f --- /dev/null +++ b/api/train_search_handler.php @@ -0,0 +1,18 @@ + 'From, To, and Date are required.']); + exit; +} + +$api = new RailApi(); +$response = $api->searchTrains($from, $to, $date); + +echo json_encode($response); +?> \ No newline at end of file diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..9c7a660 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,127 @@ + +:root { + --primary-color: #00a8ff; + --primary-hover-color: #007bff; + --dark-bg-color: #0a0a0a; + --light-bg-color: #1a1a1a; + --text-color: #e0e0e0; + --border-color: #00a8ff; + --border-radius: 12px; + --box-shadow: 0 10px 30px rgba(0, 168, 255, 0.1); + --font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif; +} + +body { + background: var(--dark-bg-color); + color: var(--text-color); + font-family: var(--font-family); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.navbar { + background: transparent !important; + transition: background 0.3s ease; + padding: 1rem 0; +} + +.navbar-brand { + font-size: 1.75rem; + font-weight: 700; + color: var(--primary-color) !important; + letter-spacing: -1px; +} + +.nav-link { + color: var(--text-color) !important; + font-weight: 500; + margin: 0 0.5rem; + padding: 0.5rem 1rem !important; + border-radius: var(--border-radius); + transition: color 0.3s, background 0.3s; +} + +.nav-link.active, +.nav-link:hover { + background: var(--primary-color); + color: #fff !important; +} + +.card { + background: var(--light-bg-color); + border: none; + border-radius: var(--border-radius); + box-shadow: var(--box-shadow); + overflow: hidden; + transition: transform 0.3s, box-shadow 0.3s; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 40px rgba(0, 168, 255, 0.2); +} + +.card-header { + background: linear-gradient(135deg, var(--primary-color), var(--primary-hover-color)); + color: #fff; + font-size: 1.25rem; + font-weight: 600; + border-bottom: none; + padding: 1.5rem; +} + +.form-control, +.form-select { + background: #2b2b2b; + color: var(--text-color); + border: 1px solid #444; + border-radius: 8px; + padding: 0.75rem 1rem; + transition: border-color 0.3s, box-shadow 0.3s; +} + +.form-control:focus, +.form-select:focus { + background: #2b2b2b; + color: #fff; + border-color: var(--primary-color); + box-shadow: 0 0 15px rgba(0, 168, 255, 0.3); +} + +.btn-primary { + background: var(--primary-color); + border: none; + border-radius: 8px; + font-weight: 600; + padding: 0.75rem 1.5rem; + transition: background-color 0.3s, transform 0.3s; +} + +.btn-primary:hover { + background: var(--primary-hover-color); + transform: translateY(-2px); +} + +.page-title { + font-size: 3rem; + font-weight: 800; + letter-spacing: -2px; + color: #fff; + text-align: center; + margin-bottom: 2rem; +} + +.result-container { + background: var(--light-bg-color); + border-radius: var(--border-radius); + padding: 2rem; + margin-top: 2rem; + box-shadow: var(--box-shadow); +} + +#live-train-map { + height: 400px; + border-radius: var(--border-radius); + border: 1px solid var(--border-color); +} + diff --git a/assets/js/live_station.js b/assets/js/live_station.js new file mode 100644 index 0000000..4e4a7ea --- /dev/null +++ b/assets/js/live_station.js @@ -0,0 +1,50 @@ +document.addEventListener('DOMContentLoaded', function() { + const liveStationForm = document.getElementById('live-station-form'); + + if (liveStationForm) { + liveStationForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const stationCode = document.getElementById('station-code').value; + const hours = document.getElementById('hours').value; + const resultDiv = document.getElementById('live-station-result'); + + resultDiv.innerHTML = '
Loading...
'; + + fetch(`api/live_station_handler.php?station_code=${stationCode}&hours=${hours}`) + .then(response => response.json()) + .then(data => { + if(data.ResponseCode == 200 && data.Trains.length > 0) { + let trainsHtml = ''; + data.Trains.forEach(train => { + trainsHtml += ` + ${train.TrainNo} + ${train.TrainName} + ${train.Source} + ${train.Destination} + ${train.ExpectedArrival} + ${train.Platform} + `; + }); + + resultDiv.innerHTML = ` +
Trains arriving at ${data.Station.StationName}
+ + + + + ${trainsHtml} +
Train NoTrain NameFromToETAPlatform
+ `; + + } else { + resultDiv.innerHTML = `
${data.Message || 'No trains found for this station in the selected time frame.'}
`; + } + }) + .catch(err => { + console.error('Error:', err); + resultDiv.innerHTML = `
An error occurred.
`; + }); + }); + } +}); \ No newline at end of file diff --git a/assets/js/live_train.js b/assets/js/live_train.js new file mode 100644 index 0000000..8e036ce --- /dev/null +++ b/assets/js/live_train.js @@ -0,0 +1,64 @@ +document.addEventListener('DOMContentLoaded', function() { + const liveTrainForm = document.getElementById('live-train-form'); + let map = null; // Variable to hold the map instance + let trainMarker = null; // Variable to hold the train marker + + if (liveTrainForm) { + liveTrainForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const trainNumber = document.getElementById('train-number').value; + // Use today's date for the demo + const trainDate = new Date().toISOString().slice(0, 10).replace(/-/g, ''); + const resultDiv = document.getElementById('live-train-result'); + + resultDiv.innerHTML = '
Loading...
'; + + fetch(`api/live_train_status_handler.php?train_number=${trainNumber}&date=${trainDate}`) + .then(response => response.json()) + .then(data => { + if(data.ResponseCode == 200) { + // Handle route display + let routeHtml = ''; + data.Route.forEach(station => { + let statusClass = station.IsCurrentStation ? 'text-primary fw-bold' : ''; + routeHtml += `
  • + ${station.StationName} (${station.StationCode})
    + Arrival: ${station.ActualArrival} | Departure: ${station.ActualDeparture} +
  • `; + }); + resultDiv.innerHTML = ` +
    Current Status: ${data.Position}
    + + `; + + // Handle map display + const coords = data.CurrentStation; + if (coords.latitude && coords.longitude) { + const latLng = [coords.latitude, coords.longitude]; + if (!map) { + // Initialize map + map = L.map('live-train-map').setView(latLng, 13); + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' + }).addTo(map); + trainMarker = L.marker(latLng).addTo(map); + } else { + // Update map + map.setView(latLng, 13); + trainMarker.setLatLng(latLng); + } + trainMarker.bindPopup(`${data.TrainName}
    ${data.Position}`).openPopup(); + } + + } else { + resultDiv.innerHTML = `
    ${data.Message || 'Could not fetch live train status.'}
    `; + } + }) + .catch(err => { + console.error('Error:', err); + resultDiv.innerHTML = `
    An error occurred.
    `; + }); + }); + } +}); diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..06d24f9 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,49 @@ +document.addEventListener('DOMContentLoaded', function() { + + const pnrForm = document.getElementById('pnr-form'); + + if (pnrForm) { + pnrForm.addEventListener('submit', function(event) { + event.preventDefault(); + const pnrNumber = document.getElementById('pnr-number').value; + const resultDiv = document.getElementById('pnr-result'); + + resultDiv.innerHTML = '
    Loading...
    '; + + fetch(`api/pnr_handler.php?pnr=${pnrNumber}`) + .then(response => response.json()) + .then(data => { + if (data.ResponseCode == 200) { + let passengerHtml = ''; + data.Passengers.forEach((p, index) => { + passengerHtml += ` + ${index + 1} + ${p.BookingStatus} + ${p.CurrentStatus} + `; + }); + + resultDiv.innerHTML = ` +
    ${data.TrainName} (${data.TrainNo})
    +

    From: ${data.From} To: ${data.To} Date: ${data.Doj}

    + + + + + + ${passengerHtml} + +
    #Booking StatusCurrent Status
    +

    Charting Status: ${data.ChartingStatus}

    + `; + } else { + resultDiv.innerHTML = `
    ${data.Message || 'Could not fetch PNR status. Please check the PNR and try again.'}
    `; + } + }) + .catch(error => { + console.error('Error:', error); + resultDiv.innerHTML = `
    An error occurred while fetching data.
    `; + }); + }); + } +}); diff --git a/assets/js/train_search.js b/assets/js/train_search.js new file mode 100644 index 0000000..416054b --- /dev/null +++ b/assets/js/train_search.js @@ -0,0 +1,33 @@ +document.addEventListener('DOMContentLoaded', function() { + const trainSearchForm = document.getElementById('train-search-form'); + + if (trainSearchForm) { + trainSearchForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const from = document.getElementById('from-station').value; + const to = document.getElementById('to-station').value; + const date = document.getElementById('search-date').value.replace(/-/g, ''); + const resultDiv = document.getElementById('train-search-result'); + + resultDiv.innerHTML = '
    Loading...
    '; + + fetch(`api/train_search_handler.php?from=${from}&to=${to}&date=${date}`) + .then(response => response.json()) + .then(data => { + if(data.error) { + resultDiv.innerHTML = `
    ${data.error}
    `; + } else if (data.ResponseCode == 200 && data.Trains.length > 0) { + // This part is a placeholder for when the API supports it. + resultDiv.innerHTML = `
    Found trains! (Display logic to be implemented)
    `; + } else { + resultDiv.innerHTML = `
    ${data.Message || 'No trains found.'}
    `; + } + }) + .catch(err => { + console.error('Error:', err); + resultDiv.innerHTML = `
    An error occurred.
    `; + }); + }); + } +}); \ No newline at end of file diff --git a/db/migrate.php b/db/migrate.php new file mode 100644 index 0000000..4690a05 --- /dev/null +++ b/db/migrate.php @@ -0,0 +1,12 @@ +exec($sql); + echo "Migration applied successfully!\n"; +} catch (PDOException $e) { + die("Migration failed: " . $e->getMessage() . "\n"); +} + diff --git a/db/migrations/001_create_stations_table.sql b/db/migrations/001_create_stations_table.sql new file mode 100644 index 0000000..96d9fbe --- /dev/null +++ b/db/migrations/001_create_stations_table.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS stations ( + id INT AUTO_INCREMENT PRIMARY KEY, + station_code VARCHAR(10) NOT NULL UNIQUE, + station_name VARCHAR(255) NOT NULL, + latitude DECIMAL(10, 8) NOT NULL, + longitude DECIMAL(11, 8) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/seed_stations.php b/db/seed_stations.php new file mode 100644 index 0000000..36b1676 --- /dev/null +++ b/db/seed_stations.php @@ -0,0 +1,28 @@ +prepare("INSERT INTO stations (station_code, station_name, latitude, longitude) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE station_name=VALUES(station_name), latitude=VALUES(latitude), longitude=VALUES(longitude)"); + + foreach ($station_data as $row) { + $stmt->execute($row); + } + + echo "Successfully seeded stations table with " . count($station_data) . " records.\n"; + +} catch (PDOException $e) { + die("Database seeding failed: " . $e->getMessage() . "\n"); +} + diff --git a/index.php b/index.php index 7205f3d..9811757 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,28 @@ - - - - - - New Style - - - - - - - - - - - - - - - - - - - - - -
    -
    -

    Analyzing your requirements and generating your website…

    -
    - Loading… -
    -

    AI is collecting your requirements and applying the first changes.

    -

    This page will update automatically as the plan is implemented.

    -

    Runtime: PHP — UTC

    -
    -
    - - - +$page = $_GET['page'] ?? 'home'; + +switch ($page) { + case 'pnr': + require_once 'pages/pnr.php'; + break; + case 'live_train': + require_once 'pages/live_train_status.php'; + break; + case 'train_search': + require_once 'pages/train_search.php'; + break; + case 'live_station': + require_once 'pages/live_station.php'; + break; + case 'seat_availability': + require_once 'pages/seat_availability.php'; + break; + default: + require_once 'pages/home.php'; + break; +} + +require_once 'templates/footer.php'; +?> \ No newline at end of file diff --git a/pages/home.php b/pages/home.php new file mode 100644 index 0000000..9dc9078 --- /dev/null +++ b/pages/home.php @@ -0,0 +1,5 @@ +
    +

    Welcome to RailGaadi

    +

    Your one-stop solution for Indian train information.

    + Get Started +
    \ No newline at end of file diff --git a/pages/live_station.php b/pages/live_station.php new file mode 100644 index 0000000..2083b4e --- /dev/null +++ b/pages/live_station.php @@ -0,0 +1,29 @@ +
    +
    +
    +
    +

    Live Station Arrivals

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    diff --git a/pages/live_train_status.php b/pages/live_train_status.php new file mode 100644 index 0000000..72def4e --- /dev/null +++ b/pages/live_train_status.php @@ -0,0 +1,26 @@ +
    +
    +
    +
    +

    Live Train Status

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/pages/pnr.php b/pages/pnr.php new file mode 100644 index 0000000..db4e3ce --- /dev/null +++ b/pages/pnr.php @@ -0,0 +1,21 @@ +
    +
    +
    +
    +

    PNR Status Check

    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    diff --git a/pages/train_search.php b/pages/train_search.php new file mode 100644 index 0000000..a83b899 --- /dev/null +++ b/pages/train_search.php @@ -0,0 +1,32 @@ +
    +
    +
    +
    +

    Search Trains Between Stations

    +
    +
    +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    diff --git a/templates/footer.php b/templates/footer.php new file mode 100644 index 0000000..3e25a9b --- /dev/null +++ b/templates/footer.php @@ -0,0 +1,21 @@ + + + + + + + + +'; + } +} +?> + + diff --git a/templates/header.php b/templates/header.php new file mode 100644 index 0000000..3f5a003 --- /dev/null +++ b/templates/header.php @@ -0,0 +1,44 @@ + + + + + + RailGaadi + + + + + + + +
    + +
    + +
    +