source: src/main/resources/static/FlightSearch.html@ 57e58a3

Last change on this file since 57e58a3 was 57e58a3, checked in by ste08 <sjovanoska@…>, 4 months ago

Initial commit

  • Property mode set to 100644
File size: 11.6 KB
Line 
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Flight Search</title>
7 <link rel="stylesheet" href="/css/main.css">
8 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
9 <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
10</head>
11<body>
12
13<div id="app" class="flight-search">
14 <header class="app-header">
15 <button class="report-issue-btn" @click="showReportPopup">Report Issue</button>
16 <button class="report-issue-btn" @click="goToWishlistPage">🤍</button>
17 <button class="logout-btn" @click="logout">Log Out</button>
18 </header>
19
20 <div class="main-content">
21 <!-- Left side: Flight Search Form -->
22 <div class="search-form-container">
23 <h1>Flight Search</h1>
24
25 <div class="search-form">
26 <label for="departure-city">Departure From</label>
27 <select v-model="departureCity" id="departure-city">
28 <option value="" disabled selected>Select a departure city</option>
29 <option v-for="city in cities" :key="city" :value="city">{{ city }}</option>
30 </select>
31
32 <label for="destination">Destination</label>
33 <select v-model="destination" id="destination">
34 <option value="" disabled selected>Select a destination</option>
35 <option v-for="place in places" :key="place" :value="place">{{ place }}</option>
36 </select>
37
38 <label for="departure-date">Departure Date</label>
39 <input type="date" v-model="departureDate" id="departureDate" />
40
41 <div class="toggle-wrapper">
42 <label for="return-date-toggle">Include Return Date</label>
43 <input type="checkbox" v-model="showReturnDate" id="return-date-toggle" />
44 </div>
45
46 <div v-if="showReturnDate">
47 <label for="return-date">Return Date</label>
48 <input type="date" v-model="returnDate" id="returnDate" />
49 </div>
50
51 <button @click="searchFlights">Search Flights</button>
52 </div>
53 </div>
54
55 <!-- Right side: Available Flights List -->
56 <div class="flights-list-container" v-if="flights.length">
57 <h2>Available Flights</h2>
58 <div class="flights-list">
59 <div class="flight-item" v-for="flight in flights" :key="flight.flightId">
60 <input type="checkbox" v-model="flight.selected" />
61 <span>{{flight.departureTime}} | {{flight.arrivalTime}} | ${{ flight.price }} | {{flight.availableSeats}}</span>
62
63 <!-- Heart icon for Wishlist -->
64 <span class="wishlist-heart" @click="toggleWishlist(flight)">
65 {{ flight.wishlisted ? '❤️' : '🤍' }}
66 </span>
67 </div>
68 </div>
69
70 <!-- Book Button (Only appears if at least one flight is selected) -->
71 <button v-if="selectedFlights.length" @click="bookFlights" class="book-btn">
72 Book
73 </button>
74
75 </div>
76 </div>
77
78 <!-- Popup Modal for Reporting an Issue -->
79 <div v-if="showPopup" class="popup-overlay">
80 <div class="popup">
81 <h3>Report an Issue</h3>
82 <textarea v-model="issueDescription" placeholder="Describe the issue here..." rows="5"></textarea>
83 <div class="popup-actions">
84 <button @click="submitIssue" class="submit-btn">Submit</button>
85 <button @click="closePopup" class="cancel-btn">Cancel</button>
86 </div>
87 </div>
88 </div>
89</div>
90
91<script>
92 new Vue({
93 el: '#app',
94 data: {
95 departureCity: '',
96 destination: '',
97 departureDate: '',
98 returnDate: '',
99 flights: [],
100 cities: [],
101 places: [],
102 bookings: [],
103 showReturnDate: false,
104 showPopup: false,
105 issueDescription: ""
106 },
107 computed: {
108 selectedFlights() {
109 return this.flights.filter(flight => flight.selected);
110 }
111 },
112 methods: {
113 async searchFlights() {
114 console.log("button clicked");
115
116 if (this.departureCity && this.destination && this.departureDate) {
117 console.log("Search parameters are valid.");
118
119 try {
120 // Log the params being sent
121 console.log("Params being sent:", {
122 departureCity: this.departureCity,
123 destination: this.destination,
124 departureDate: this.departureDate,
125 returnDate: this.showReturnDate ? this.returnDate : null
126 });
127
128 const response = await axios.get('/api/flights/flight-search', {
129 params: {
130 departureCity: this.departureCity,
131 destination: this.destination,
132 departureDate: this.departureDate,
133 returnDate: this.showReturnDate ? this.returnDate : null
134 }
135 });
136
137 console.log("Response received:", response.data);
138
139 // Handle no results
140 if (response.data && response.data.length > 0) {
141 this.flights = response.data;
142 console.log("Flights found:", this.flights);
143 } else {
144 this.flights = [];
145 alert("No flights found for the given criteria.");
146 }
147
148 } catch (error) {
149 console.error("Error fetching flights", error);
150 }
151 } else {
152 alert("Please select departure city, destination, and date");
153 this.flights = [];
154 }
155 }
156,
157 bookFlights() {
158 if (!this.selectedFlights.length) {
159 alert("Please select at least one flight.");
160 return;
161 }
162 const flight = this.selectedFlights[0];
163 console.log(this.selectedFlights[0]);
164 const totalCost = flight.price;
165 const bookingDate = new Date().toISOString().split('T')[0];
166
167 const bookingData = {
168 flightId: flight.flightId,
169 bookingDate: bookingDate,
170 status: 'PENDING',
171 totalCost: totalCost
172 };
173 console.log("Booking Data",bookingData);
174 axios.post('/api/bookings', bookingData)
175 .then(response => {
176 alert("Booked successfully!");
177 window.location.href = `/transaction?amount=${encodeURIComponent(totalCost)}`;
178 })
179 .catch(error => {
180 console.error("Error booking flight", error);
181 alert("There was an error creating your booking. Please try again.");
182 });
183 },
184 logout() {
185 window.location.href = '/login';
186 },
187 async toggleWishlist(flight) {
188 flight.wishlisted = !flight.wishlisted;
189
190 const wishlistData = {
191 targetId: flight.flightId,
192 wishlisted: flight.wishlisted
193 };
194 try {
195 const response = await axios.post('/api/wishlists', wishlistData);
196 console.log("Wishlist updated");
197 } catch (error) {
198 console.error("Error updating wishlist:", error.response ? error.response.data : error.message);
199 }
200 },
201 goToWishlistPage() {
202 window.location.href = '/wishlist';
203 },
204 showReportPopup() {
205 this.showPopup = true;
206 },
207 closePopup() {
208 this.showPopup = false;
209 },
210 submitIssue() {
211 const flight = this.selectedFlights[0];
212 if (this.issueDescription.trim()) {
213 const reviewData = {
214 userID: 1,
215 subject: this.subject,
216 description: this.issueDescription
217 };
218
219 axios.post('/api/support-tickets', reviewData)
220 .then(response => {
221 alert("Issue reported successfully!");
222 this.closePopup();
223 })
224 .catch(error => {
225 console.error("Error submitting issue:", error.response ? error.response.data : error.message);
226 alert("There was an error submitting your issue. Please try again.");
227 });
228 } else {
229 alert("Please enter a description for the issue.");
230 }
231 },
232 leaveReview() {
233 const flight = this.selectedFlights[0];
234 if (this.issueDescription.trim()) {
235 const reviewData = {
236 userID: 1,
237 targetID: flight.flightId,
238 reviewComment: this.issueDescription,
239 rating: 5,
240 date: new Date().toISOString().split('T')[0]
241 };
242
243 axios.post('/api/support-tickets', reviewData)
244 .then(response => {
245 alert("Issue reported successfully!");
246 this.closePopup();
247 })
248 .catch(error => {
249 console.error("Error submitting issue:", error.response ? error.response.data : error.message);
250 alert("There was an error submitting your issue. Please try again.");
251 });
252 } else {
253 alert("Please enter a description for the issue.");
254 }
255 },
256 async fetchFlights() {
257 try {
258 const response = await axios.get('/api/destinations');
259
260 this.cities = response.data.map(departureCity => departureCity.name);
261 this.places = response.data.map(destination => destination.name);
262 } catch (error) {
263 console.error("Error fetching Destinations", error);
264 }
265 }
266 },
267 mounted() {
268 this.fetchFlights();
269 axios.get('api/flights')
270 .then(response => {
271 this.flights = response.data;
272 })
273 .catch(error => {
274 console.error("Error fetching flights", error);
275 });
276 axios.get('api/bookings/getAll/${flight.flightID}')
277 .then(response => {
278 console.log(response.data);
279 this.bookings = response.data;
280 })
281 .catch(error => {
282 console.error("Error fetching flights", error);
283 })
284 }
285 });
286</script>
287
288</body>
289</html>
Note: See TracBrowser for help on using the repository browser.