Changeset 9868304 for src/main


Ignore:
Timestamp:
02/17/25 01:39:28 (4 months ago)
Author:
ste08 <sjovanoska@…>
Branches:
master
Children:
de83113
Parents:
a70b5a4
git-author:
ste08 <sjovanoska@…> (02/17/25 01:39:02)
git-committer:
ste08 <sjovanoska@…> (02/17/25 01:39:28)
Message:

Frontend + some backend changes

Location:
src/main
Files:
4 added
1 deleted
10 edited
3 moved

Legend:

Unmodified
Added
Removed
  • src/main/java/com/example/skychasemk/controller/ApplicationUserController.java

    ra70b5a4 r9868304  
    22
    33import com.example.skychasemk.dto.ApplicationUserDTO;
     4import com.example.skychasemk.dto.ApplicationUserLoginDTO;
    45import com.example.skychasemk.model.ApplicationUser;
    56import com.example.skychasemk.services.ApplicationUserService;
     
    89import org.springframework.http.ResponseEntity;
    910import org.springframework.web.bind.annotation.*;
     11
     12import java.util.HashMap;
     13import java.util.Map;
    1014
    1115@RestController
     
    2226        return ResponseEntity.ok("User saved successfully");
    2327    }
    24 
     28    @PostMapping("/login")
     29    public ResponseEntity<Map<String,Long>> loginUser(@Valid @RequestBody ApplicationUserLoginDTO userDTO) {
     30        ApplicationUser loginUser = userService.findByEmail(userDTO);
     31        Map<String,Long> response = new HashMap<>();
     32        response.put("userId",loginUser.getUserid());
     33        return ResponseEntity.ok(response);
     34    }
    2535}
  • src/main/java/com/example/skychasemk/dto/ApplicationUserDTO.java

    ra70b5a4 r9868304  
    2222    private String password;
    2323
    24     private String phoneNumber;
     24    private String phone_number;
     25
     26    public String getPhone_number() {
     27        return phone_number;
     28    }
     29
     30    public void setPhone_number(String phone_number) {
     31        this.phone_number = phone_number;
     32    }
    2533}
  • src/main/java/com/example/skychasemk/model/ApplicationUser.java

    ra70b5a4 r9868304  
    3131    @Column(name = "phone_number")
    3232
    33     private String phoneNumber;
     33    private String phone_number;
    3434
    3535    @Column(name = "date_joined")
     
    4141    }
    4242
     43    public void setPhoneNumber(String phoneNumber) {
     44        this.phone_number = phoneNumber;
     45    }
    4346}
  • src/main/java/com/example/skychasemk/repository/ApplicationUserRepository.java

    ra70b5a4 r9868304  
    1111@Repository
    1212public interface ApplicationUserRepository extends JpaRepository<ApplicationUser, Long> {
    13     Optional<ApplicationUser> findByEmail(String email);
    1413    @Query("SELECT u FROM ApplicationUser u WHERE u.userid = :id")
    1514    Optional<ApplicationUser> getUserById(@Param("id") Long userid);
     15    @Query("SELECT u FROM ApplicationUser  u WHERE u.email=:email")
     16    Optional<ApplicationUser> findByEmail(@Param("email") String email);
    1617}
  • src/main/java/com/example/skychasemk/services/ApplicationUserService.java

    ra70b5a4 r9868304  
    22
    33import com.example.skychasemk.dto.ApplicationUserDTO;
     4import com.example.skychasemk.dto.ApplicationUserLoginDTO;
    45import com.example.skychasemk.model.ApplicationUser;
    56import com.example.skychasemk.repository.ApplicationUserRepository;
    67import jakarta.transaction.Transactional;
     8import jakarta.validation.Valid;
    79import org.springframework.beans.factory.annotation.Autowired;
    810import org.springframework.stereotype.Service;
    911
    10 import java.time.Instant;
    11 import java.time.LocalDate;
     12import java.util.Optional;
    1213//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    1314
     
    3233        user.setEmail(userDTO.getEmail());
    3334        user.setPassword(userDTO.getPassword());
    34         user.setPhoneNumber(userDTO.getPhoneNumber());
     35        user.setPhoneNumber(userDTO.getPhone_number());
    3536        ApplicationUser savedUser = userRepository.save(user);
    3637        userRepository.flush();
    3738        return savedUser;
    3839    }
     40
     41    public ApplicationUser findByEmail(@Valid ApplicationUserLoginDTO userDTO) {
     42        if (userRepository.findByEmail(userDTO.getEmail()).isEmpty()) {
     43            throw new RuntimeException("User not registered");
     44        } else {
     45            Optional<ApplicationUser> userId = userRepository.findByEmail(userDTO.getEmail());
     46            return userId.get();
     47        }
     48    }
    3949}
  • src/main/resources/static/FlightSearch.html

    ra70b5a4 r9868304  
    88    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    99    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
     10    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
     11    <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css'>
     12    <style>
     13        body {
     14            background: url('images/flight.jpg') no-repeat center center fixed;
     15            background-size: cover;
     16            display: flex;
     17            flex-direction: column;
     18            align-items: center;
     19            justify-content: center;
     20            height: 100vh;
     21            margin: 0;
     22            font-family: Arial, sans-serif;
     23        }
     24
     25        .header {
     26            position: absolute;
     27            top: 0;
     28            left: 0;
     29            display: flex;
     30            align-items: center;
     31            background-color: rebeccapurple;
     32            padding: 10px;
     33            width: 100%;
     34            z-index: 10;
     35        }
     36        .header img {
     37            width: 40px;
     38            height: 40px;
     39            margin-right: 20px;
     40        }
     41
     42        .header h1 {
     43            color: white;
     44            margin: 0;
     45            font-size: 15px;
     46            padding-right: 50px;
     47        }
     48
     49        .header button {
     50            background-color: transparent;
     51            border: none;
     52            color: white;
     53            font-size: 14px;
     54        }
     55
     56        .header button:hover {
     57            background-color: transparent;
     58            cursor: pointer;
     59        }
     60
     61        .split {
     62            height: 100%;
     63            width: 50%;
     64            position: fixed;
     65            z-index: 1;
     66            top: 0;
     67            overflow-x: hidden;
     68            padding-top: 20px;
     69        }
     70
     71        .left {
     72            left: 0;
     73            padding:50px;
     74        }
     75
     76        .right {
     77            right: 0;
     78            padding:10px;
     79        }
     80        select {
     81            -webkit-appearance: none;
     82            -moz-appearance: none;
     83            appearance: none;
     84            border: 0;
     85            outline: 0;
     86            font: inherit;
     87            width: 20em;
     88            height: 3em;
     89            padding: 0 4em 0 1em;
     90            background: url(https://upload.wikimedia.org/wikipedia/commons/9/9d/Caret_down_font_awesome_whitevariation.svg) no-repeat right 0.8em center/1.4em, linear-gradient(to left, rgba(255, 255, 255, 0.3) 3em, rgba(255, 255, 255, 0.2) 3em);
     91            color: white;
     92            border-radius: 0.25em;
     93            box-shadow: 0 0 1em 0 rgba(0, 0, 0, 0.2);
     94            cursor: pointer;
     95        }
     96        select option {
     97            color: inherit;
     98            background-color: #320a28;
     99        }
     100        select:focus {
     101            outline: none;
     102        }
     103        select::-ms-expand {
     104            display: none;
     105        }
     106
     107        .search-form-container h2 {
     108            color: white;
     109            padding-top: 110px;
     110        }
     111
     112        .search-form {
     113            padding: 10px;
     114            color:white;
     115            font-family: Cambria;
     116        }
     117        .search {
     118            background-color: rebeccapurple;
     119            color: white;
     120            width: 20em;
     121            height: 3em;
     122        }
     123
     124        .book {
     125            background-color: darkblue;
     126            color: white;
     127            width: 20em;
     128            height: 3em;
     129        }
     130
     131        .search:hover {
     132            background-color: mediumpurple;
     133        }
     134
     135        .flights-list-container {
     136            color: white;
     137        }
     138
     139        .flights-list-container h2{
     140            padding-top: 110px;
     141        }
     142        .flights-list .flight-item {
     143            margin-bottom: 15px;
     144        }
     145
     146        .flights-list .flight-item span {
     147            margin-right: 15px;
     148        }
     149        .flight-item {
     150            display: flex;
     151            align-items: center;
     152            justify-content: space-between;
     153            padding: 15px;
     154            background: url(https://upload.wikimedia.org/wikipedia/commons/9/9d/Caret_down_font_awesome_whitevariation.svg) no-repeat right 0.8em center/1.4em, linear-gradient(to left, rgba(255, 255, 255, 0.3) 3em, rgba(255, 255, 255, 0.2) 3em);
     155            border-radius: 8px;
     156            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
     157            transition: transform 0.3s ease, background-color 0.3s ease;
     158            width: 70%;
     159            height: 15px;
     160        }
     161
     162        .popup-overlay {
     163            position: fixed;
     164            top: 0;
     165            left: 0;
     166            width: 100%;
     167            height: 100%;
     168            background: rgba(0, 0, 0, 0.7);
     169            display: flex;
     170            align-items: center;
     171            justify-content: center;
     172        }
     173
     174        .popup {
     175            background-color: white;
     176            padding: 20px;
     177            width: 300px;
     178            border-radius: 10px;
     179        }
     180
     181        .popup button {
     182            margin-top: 10px;
     183            background-color: rebeccapurple;
     184            color: white;
     185            border: none;
     186            padding: 5px;
     187            cursor: pointer;
     188        }
     189
     190        .popup button:hover {
     191            background-color: mediumpurple;
     192        }
     193
     194        .calendar {
     195            background-color: transparent;
     196            border-radius: 2px;
     197            border-color: white;
     198            width: 18.6em;
     199            height: 2.5em;
     200            color:white;
     201        }
     202    </style>
    10203</head>
    11204<body>
    12205
    13206<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>
     207    <header class="header">
     208        <button @click="home"><img src="/images/home.png" alt="Home Icon"></button>
     209        <button @click="showReportPopup">Report Issue</button>
     210        <button @click="goToWishlistPage">🤍</button>
     211        <button @click="home">Log Out</button>
    18212    </header>
    19213
    20     <div class="main-content">
    21         <!-- Left side: Flight Search Form -->
     214    <div class="split left">
    22215        <div class="search-form-container">
    23             <h1>Flight Search</h1>
     216            <h2>Search flights</h2>
    24217
    25218            <div class="search-form">
    26219                <label for="departure-city">Departure From</label>
     220                <br>
    27221                <select v-model="departureCity" id="departure-city">
    28222                    <option value="" disabled selected>Select a departure city</option>
     
    31225
    32226                <label for="destination">Destination</label>
     227                <br>
    33228                <select v-model="destination" id="destination">
    34229                    <option value="" disabled selected>Select a destination</option>
     
    37232
    38233                <label for="departure-date">Departure Date</label>
    39                 <input type="date" v-model="departureDate" id="departureDate" />
    40 
     234                <br>
     235                <input class="calendar" type="date" v-model="departureDate" id="departureDate" />
     236                <br>
    41237                <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" />
     238                    <label for="return-date-toggle">Include Return Date<input type="checkbox" v-model="showReturnDate" id="return-date-toggle" /></label>
    44239                </div>
    45 
     240                <br>
    46241                <div v-if="showReturnDate">
    47242                    <label for="return-date">Return Date</label>
    48                     <input type="date" v-model="returnDate" id="returnDate" />
     243                    <input class="calendar" type="date" v-model="returnDate" id="returnDate" />
    49244                </div>
    50 
    51                 <button @click="searchFlights">Search Flights</button>
     245                <br>
     246                <button class="search" @click="searchFlights">Search Flights</button>
    52247            </div>
    53248        </div>
    54 
    55         <!-- Right side: Available Flights List -->
    56         <div class="flights-list-container" v-if="flights.length">
     249    </div>
     250    <div class="split right">
     251        <div class="flights-list-container" v-show="isContainerVisible" v-if="flights.length">
    57252            <h2>Available Flights</h2>
    58253            <div class="flights-list">
    59254                <div class="flight-item" v-for="flight in flights" :key="flight.flightId">
    60255                    <input type="checkbox" v-model="flight.selected" />
    61                     <span>{{flight.departureTime}} | {{flight.arrivalTime}} | ${{ flight.price }} | {{flight.availableSeats}}</span>
    62 
    63                     <!-- Heart icon for Wishlist -->
     256                    <span>{{ flight.departureTime }} | {{ flight.arrivalTime }} | ${{ flight.price }} | {{ flight.availableSeats }}</span>
     257
    64258                    <span class="wishlist-heart" @click="toggleWishlist(flight)">
    65259                        {{ flight.wishlisted ? '❤️' : '🤍' }}
     
    68262            </div>
    69263
    70             <!-- Book Button (Only appears if at least one flight is selected) -->
    71             <button v-if="selectedFlights.length" @click="bookFlights" class="book-btn">
     264            <button v-if="selectedFlights.length" @click="bookFlights"  class="book">
    72265                Book
    73266            </button>
    74 
    75267        </div>
    76268    </div>
    77269
    78     <!-- Popup Modal for Reporting an Issue -->
    79270    <div v-if="showPopup" class="popup-overlay">
    80271        <div class="popup">
     
    93284        el: '#app',
    94285        data: {
     286            isContainerVisible:false,
    95287            departureCity: '',
    96288            destination: '',
     
    112304        methods: {
    113305            async searchFlights() {
    114                 console.log("button clicked");
    115 
     306                this.isContainerVisible = !this.isContainerVisible;
    116307                if (this.departureCity && this.destination && this.departureDate) {
    117                     console.log("Search parameters are valid.");
    118 
    119308                    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 
    128309                        const response = await axios.get('/api/flights/flight-search', {
    129310                            params: {
     
    135316                        });
    136317
    137                         console.log("Response received:", response.data);
    138 
    139                         // Handle no results
    140318                        if (response.data && response.data.length > 0) {
    141319                            this.flights = response.data;
    142                             console.log("Flights found:", this.flights);
    143320                        } else {
    144321                            this.flights = [];
    145322                            alert("No flights found for the given criteria.");
    146323                        }
    147 
    148324                    } catch (error) {
    149325                        console.error("Error fetching flights", error);
    150326                    }
    151327                } else {
    152                     alert("Please select departure city, destination, and date");
     328                    alert("Please select departure city, destination, and date.");
    153329                    this.flights = [];
    154330                }
    155             }
    156 ,
     331            },
    157332            bookFlights() {
    158333                if (!this.selectedFlights.length) {
     
    160335                    return;
    161336                }
     337
    162338                const flight = this.selectedFlights[0];
    163                 console.log(this.selectedFlights[0]);
    164339                const totalCost = flight.price;
    165                 const bookingDate = new Date().toISOString().split('T')[0];
    166 
    167 
    168340                const bookingData = {
    169                     flightId: flight.flightID,
    170                     bookingDate: bookingDate,
     341                    flightId: flight.flightId,
     342                    bookingDate: new Date().toISOString().split('T')[0],
    171343                    status: 'PENDING',
    172344                    totalCost: totalCost
    173345                };
    174                 console.log("Booking Data",bookingData);
     346
    175347                axios.post('/api/bookings', bookingData)
    176348                    .then(response => {
    177349                        const bookingID = response.data.bookingID;
    178350                        alert("Booked successfully!");
    179                         window.location.href = `/transaction?amount=${encodeURIComponent(totalCost)}&bookingId=${encodeURIComponent(bookingID)}&flightId=${encodeURIComponent(flight.flightID)}`;
     351                        window.location.href = `/transaction?amount=${encodeURIComponent(totalCost)}&bookingId=${encodeURIComponent(bookingID)}&flightId=${encodeURIComponent(flight.flightId)}`;
    180352                    })
    181353                    .catch(error => {
     
    184356                    });
    185357            },
    186             logout() {
    187                 window.location.href = '/login';
     358            home() {
     359                window.location.href = '/';
    188360            },
    189361            async toggleWishlist(flight) {
    190362                flight.wishlisted = !flight.wishlisted;
    191 
    192363                const wishlistData = {
    193                     targetId: flight.flightID,
     364                    targetId: flight.flightId,
    194365                    wishlisted: flight.wishlisted
    195366                };
    196367                try {
    197                     const response = await axios.post('/api/wishlists', wishlistData);
    198                     console.log("Wishlist updated");
     368                    await axios.post('/api/wishlists', wishlistData);
    199369                } catch (error) {
    200                     console.error("Error updating wishlist:", error.response ? error.response.data : error.message);
     370                    console.error("Error updating wishlist:", error);
    201371                }
    202372            },
    203373            goToWishlistPage() {
    204                 window.location.href = '/wishlist';
     374                window.location.href = '/api/wishlists';
    205375            },
    206376            showReportPopup() {
     
    211381            },
    212382            submitIssue() {
    213                 const flight = this.selectedFlights[0];
    214383                if (this.issueDescription.trim()) {
    215384                    const reviewData = {
    216385                        userID: 1,
    217                         subject: this.subject,
     386                        subject: "Issue Report",
    218387                        description: this.issueDescription
    219388                    };
     
    225394                        })
    226395                        .catch(error => {
    227                             console.error("Error submitting issue:", error.response ? error.response.data : error.message);
     396                            console.error("Error submitting issue:", error);
    228397                            alert("There was an error submitting your issue. Please try again.");
    229398                        });
     
    232401                }
    233402            },
    234             leaveReview() {
    235                 const flight = this.selectedFlights[0];
    236                 if (this.issueDescription.trim()) {
    237                     const reviewData = {
    238                         userID: 1,
    239                         targetID: flight.flightId,
    240                         reviewComment: this.issueDescription,
    241                         rating: 5,
    242                         date: new Date().toISOString().split('T')[0]
    243                     };
    244 
    245                     axios.post('/api/support-tickets', reviewData)
    246                         .then(response => {
    247                             alert("Issue reported successfully!");
    248                             this.closePopup();
    249                         })
    250                         .catch(error => {
    251                             console.error("Error submitting issue:", error.response ? error.response.data : error.message);
    252                             alert("There was an error submitting your issue. Please try again.");
    253                         });
    254                 } else {
    255                     alert("Please enter a description for the issue.");
    256                 }
    257             },
    258403            async fetchFlights() {
    259404                try {
    260405                    const response = await axios.get('/api/destinations');
    261 
    262406                    this.cities = response.data.map(departureCity => departureCity.name);
    263407                    this.places = response.data.map(destination => destination.name);
     
    276420                    console.error("Error fetching flights", error);
    277421                });
    278             axios.get('api/bookings/getAll/${flight.flightId}')
    279                 .then(response => {
    280                     console.log(response.data);
    281                     this.bookings = response.data;
    282                 })
    283                 .catch(error => {
    284                     console.error("Error fetching flights", error);
    285                 })
    286422        }
    287423    });
  • src/main/resources/static/TransactionPage.html

    ra70b5a4 r9868304  
    88    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    99</head>
     10<style>
     11    @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap');
     12
     13
     14    * {
     15        margin: 0;
     16        padding: 0;
     17        box-sizing: border-box;
     18        font-family: 'Poppins', sans-serif
     19    }
     20
     21    .container {
     22        margin: 10px auto;
     23        padding: 150px;
     24        padding-top:10px;
     25    }
     26
     27    .container .card {
     28        width: 100%;
     29        box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
     30        background: #fff;
     31        border-radius: 0px;
     32    }
     33
     34    body {
     35        background: #eee
     36    }
     37
     38
     39    .container .card .img-box {
     40        width: 80px;
     41        height: 50px;
     42    }
     43
     44    .container .card img {
     45        width: 100%;
     46        object-fit: fill;
     47    }
     48
     49    .container .card .number {
     50        font-size: 24px;
     51    }
     52
     53    .container .card-body .btn.btn-primary .fab.fa-cc-paypal {
     54        font-size: 32px;
     55        color: #3333f7;
     56    }
     57
     58    .fab.fa-cc-amex {
     59        color: #1c6acf;
     60        font-size: 32px;
     61    }
     62
     63    .fab.fa-cc-mastercard {
     64        font-size: 32px;
     65        color: red;
     66    }
     67
     68    .fab.fa-cc-discover {
     69        font-size: 32px;
     70        color: orange;
     71    }
     72
     73    .c-green {
     74        color: green;
     75    }
     76
     77    .box {
     78        height: 40px;
     79        width: 50px;
     80        display: flex;
     81        align-items: center;
     82        justify-content: center;
     83        background-color: #ddd;
     84    }
     85
     86    .btn.btn-primary.payment {
     87        background-color: #1c6acf;
     88        color: white;
     89        border-radius: 0px;
     90        height: 50px;
     91        display: flex;
     92        align-items: center;
     93        justify-content: center;
     94        margin-top: 24px;
     95    }
     96
     97
     98    .form__div {
     99        height: 50px;
     100        position: relative;
     101        margin-bottom: 24px;
     102    }
     103
     104    .form-control {
     105        width: 100%;
     106        height: 45px;
     107        font-size: 14px;
     108        border: 1px solid #DADCE0;
     109        border-radius: 0;
     110        outline: none;
     111        padding: 2px;
     112        background: none;
     113        z-index: 1;
     114        box-shadow: none;
     115    }
     116
     117    .form__label {
     118        position: absolute;
     119        left: 16px;
     120        top: 10px;
     121        background-color: #fff;
     122        color: #80868B;
     123        font-size: 16px;
     124        transition: .3s;
     125        text-transform: uppercase;
     126    }
     127
     128    .form-control:focus+.form__label {
     129        top: -8px;
     130        left: 12px;
     131        color: #1A73E8;
     132        font-size: 12px;
     133        font-weight: 500;
     134        z-index: 10;
     135    }
     136
     137    .form-control:not(:placeholder-shown).form-control:not(:focus)+.form__label {
     138        top: -8px;
     139        left: 12px;
     140        font-size: 12px;
     141        font-weight: 500;
     142        z-index: 10;
     143    }
     144    .input-group{
     145        align-content: center;
     146        padding-left: 500px;
     147        padding-top:10px;
     148    }
     149    .button-group{
     150        display:flex;
     151        gap:10px;
     152    }
     153    .pay-btn,
     154    .cancel-btn {
     155        padding: 10px 20px;
     156        font-size: 16px;
     157        cursor: pointer;
     158        border: none;
     159        border-radius: 5px;
     160    }
     161
     162    .pay-btn {
     163        background-color: #4CAF50; /* Green background for the pay button */
     164        color: white;
     165    }
     166
     167    .cancel-btn {
     168        background-color: #f44336; /* Red background for the cancel button */
     169        color: white;
     170    }
     171</style>
    10172<body>
    11173
    12 <div id="app" class="transaction-container">
    13     <div class="transaction-box">
    14         <h2>Complete Your Payment</h2>
    15 
    16         <form @submit.prevent="processPayment">
    17             <div class="input-group">
    18                 <label for="cardholder">Cardholder Name</label>
    19                 <input type="text" id="cardholder" v-model="cardholder" placeholder="John Doe" required />
     174<div id="app" class="container">
     175    <div class="row">
     176                <div class="col-lg-4 mb-lg-0 mb-3">
     177                    <div class="card p-3">
     178                        <div class="img-box">
     179                            <img src="https://www.freepnglogos.com/uploads/visa-logo-download-png-21.png" alt="">
     180                        </div>
     181                        <div class="number">
     182                            <label class="fw-bold" for="">**** **** **** 1060</label>
     183                        </div>
     184                        <div class="d-flex align-items-center justify-content-between">
     185                            <small><span class="fw-bold">Expiry date:</span><span>10/16</span></small>
     186                            <small><span class="fw-bold">Name:</span><span>Kumar</span></small>
     187                        </div>
     188                    </div>
     189                </div>
     190                <div class="col-lg-4 mb-lg-0 mb-3">
     191                    <div class="card p-3">
     192                        <div class="img-box">
     193                            <img src="https://www.freepnglogos.com/uploads/mastercard-png/file-mastercard-logo-svg-wikimedia-commons-4.png"
     194                                 alt="">
     195                        </div>
     196                        <div class="number">
     197                            <label class="fw-bold">**** **** **** 1060</label>
     198                        </div>
     199                        <div class="d-flex align-items-center justify-content-between">
     200                            <small><span class="fw-bold">Expiry date:</span><span>10/16</span></small>
     201                            <small><span class="fw-bold">Name:</span><span>Kumar</span></small>
     202                        </div>
     203                    </div>
     204                </div>
     205                <div class="col-lg-4 mb-lg-0 mb-3">
     206                    <div class="card p-3">
     207                        <div class="img-box">
     208                            <img src="https://www.freepnglogos.com/uploads/discover-png-logo/credit-cards-discover-png-logo-4.png"
     209                                 alt="">
     210                        </div>
     211                        <div class="number">
     212                            <label class="fw-bold">**** **** **** 1060</label>
     213                        </div>
     214                        <div class="d-flex align-items-center justify-content-between">
     215                            <small><span class="fw-bold">Expiry date:</span><span>10/16</span></small>
     216                            <small><span class="fw-bold">Name:</span><span>Kumar</span></small>
     217                        </div>
     218                    </div>
     219                </div>
     220                <div class="col-12 mt-4">
     221                    <div class="card p-3">
     222                        <p class="mb-0 fw-bold h4">Payment Methods</p>
     223                    </div>
     224                </div>
    20225            </div>
    21 
    22             <div class="input-group">
    23                 <label for="cardNumber">Card Number</label>
    24                 <input type="text"
    25                        id="cardNumber"
    26                        v-model="cardNumber"
    27                        maxlength="16"
    28                        placeholder="1234 5678 9012 3456"
    29                        required />
    30             </div>
    31 
    32             <div class="input-group">
    33                 <label for="expiration">Expiration Date</label>
    34                 <input type="month" id="expiration" v-model="expiration" required />
    35             </div>
    36 
    37             <div class="button-group">
    38                 <button type="submit" class="pay-btn">Pay</button>
    39                 <button type="button" class="cancel-btn" @click="cancelPayment">Cancel</button>
    40             </div>
    41         </form>
    42 
    43         <div v-if="paymentSuccess" class="success-message">
    44             ✅ Payment successful! Redirecting...
     226            <form class="submit" @submit.prevent="processPayment">
     227                <div class="input-group">
     228                    <label for="cardholder">Cardholder Name</label>
     229                    <input type="text" id="cardholder" v-model="cardholder" placeholder="John Doe" required />
     230                </div>
     231
     232                <div class="input-group">
     233                    <label for="cardNumber">Card Number</label>
     234                    <input type="text"
     235                           id="cardNumber"
     236                           v-model="cardNumber"
     237                           maxlength="16"
     238                           placeholder="1234 5678 9012 3456"
     239                           required />
     240                </div>
     241
     242                <div class="input-group">
     243                    <label for="expiration">Expiration Date</label>
     244                    <input type="month" id="expiration" v-model="expiration" required />
     245                </div>
     246
     247                <div class="button-group">
     248                    <button type="submit" class="pay-btn">Pay</button>
     249                    <button type="button" class="cancel-btn" @click="cancelPayment">Cancel</button>
     250                </div>
     251            </form>
    45252        </div>
    46     </div>
    47 </div>
    48253
    49254<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  • src/main/resources/static/UserLogin.html

    ra70b5a4 r9868304  
    3535        data: {
    3636            email: '',
    37             password: ''
     37            password: '',
     38            userId:''
    3839        },
    3940        methods: {
    40             loginUser() {
     41            async loginUser() {
    4142                if (this.email && this.password) {
    42                     window.location.href = '/flights';
     43                    try{
     44                        const response = await fetch('/api/user/login', {
     45                            method:'POST',
     46                            headers: {
     47                                'Content-Type':'application/json'
     48                            },
     49                            body: JSON.stringify({
     50                                email:this.email,
     51                                password:this.password
     52                            })
     53                        });
     54                        if(!response.ok){
     55                            throw new Error('Login failed');
     56                        }
     57                        const data = await response.json();
     58                        console.log(data);
     59                        if(data.userId){
     60                            console.log('Success');
     61                            window.location.href = `/flights?userId=${encodeURIComponent(data.userId)}`;
     62                        }else {
     63                            alert('Invalid login credentials');
     64                        }
     65                    } catch (error){
     66                        console.error(error);
     67                        alert('Login failed. Please try again.');
     68                    }
    4369                }
    4470            }
  • src/main/resources/static/css/main.css

    ra70b5a4 r9868304  
    11.signup-container {
    2     background-image: url('../../images/registration.jpg');
     2    background-image: url('../images/registration.jpg');
    33    background-size: cover;
    44    background-position: center;
  • src/main/resources/static/index.html

    ra70b5a4 r9868304  
    44    <meta charset="UTF-8">
    55    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6     <title>Support Tickets</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>
     6    <title>SkyChase-mk</title>
     7    <style>
     8        body {
     9            background: url('images/homepage.jpg') no-repeat center center fixed;
     10            background-size: cover;
     11            display: flex;
     12            flex-direction: column;
     13            align-items: center;
     14            justify-content: center;
     15            height: 100vh;
     16            margin: 0;
     17            font-family: Arial, sans-serif;
     18        }
     19
     20        .header {
     21            position: absolute;
     22            top: 0;
     23            left: 0;
     24            display: flex;
     25            align-items: center;
     26            background-color:rebeccapurple;
     27            padding: 10px;
     28            width: 100%;
     29        }
     30
     31        .header img {
     32            width: 40px;
     33            height: 40px;
     34            margin-right: 10px;
     35        }
     36
     37        .header h1 {
     38            color: white;
     39            margin: 0;
     40            font-size: 15px;
     41            padding-right: 50px;
     42        }
     43
     44        .buttons {
     45            text-align: center;
     46        }
     47
     48        .buttons button {
     49            padding: 15px 30px;
     50            margin: 10px;
     51            font-size: 18px;
     52            border: none;
     53            border-radius: 5px;
     54            cursor: pointer;
     55            transition: 0.3s;
     56        }
     57
     58        .signup {
     59            background-color: rebeccapurple;
     60            color: white;
     61        }
     62
     63        .signup:hover {
     64            background-color: mediumpurple;
     65        }
     66
     67        .login {
     68            background-color: #007bff;
     69            color: white;
     70        }
     71
     72        .login:hover {
     73            background-color: #0056b3;
     74        }
     75        .adminlogin {
     76            top:0;
     77            right: 0;
     78            background-color: rebeccapurple;
     79            border:0;
     80            color:white;
     81            padding: 0 1200px;
     82        }
     83    </style>
    984</head>
    1085<body>
    11 
    12 <div id="app" class="support-ticket-container">
    13     <h1>Support Tickets</h1>
    14     <div class="ticket-layout">
    15         <!-- Left side: Ticket list -->
    16         <div class="ticket-list">
    17             <div class="ticket-item"
    18                  v-for="ticket in tickets"
    19                  :key="ticket.id"
    20                  @click="selectTicket(ticket)"
    21                  :class="{'active': selectedTicket && selectedTicket.id === ticket.id}">
    22                 <div class="ticket-info">
    23                     <p><strong>Subject:</strong> {{ ticket.subject }}</p>
    24                     <p><strong>Date:</strong> {{ ticket.date }}</p>
    25                 </div>
    26                 <div class="ticket-actions">
    27                     <button @click.stop="resolveTicket(ticket.id)">Resolve</button>
    28                 </div>
    29             </div>
    30         </div>
    31 
    32         <!-- Right side: Ticket details -->
    33         <div class="ticket-details" v-if="selectedTicket">
    34             <h2>Ticket Details</h2>
    35             <p><strong>Subject:</strong> {{ selectedTicket.subject }}</p>
    36             <p><strong>Description:</strong> {{ selectedTicket.description }}</p>
    37             <p><strong>Date:</strong> {{ selectedTicket.date }}</p>
    38             <button @click="resolveTicket(selectedTicket.id)">Resolve</button>
    39         </div>
    40     </div>
     86<div class="header">
     87    <img src="/images/home.png" alt="Home Icon">
     88    <h1>SkyChase</h1>
     89    <button class="adminlogin" onclick="location.href='/admin'">Admin?</button>
    4190</div>
    4291
    43 <script>
    44     new Vue({
    45         el: '#app',
    46         data: {
    47             tickets: [
    48                 { id: 1, subject: 'Flight booking issue', description: 'Customer could not book a flight.', date: '2025-02-01' },
    49                 { id: 2, subject: 'Payment failure', description: 'Payment was not processed during checkout.', date: '2025-02-02' }
    50             ],
    51             selectedTicket: null
    52         },
    53         methods: {
    54             resolveTicket(id) {
    55                 alert(`Ticket ${id} resolved.`);
    56                 // Optionally, you can update the ticket's status or remove it
    57             },
    58             selectTicket(ticket) {
    59                 this.selectedTicket = ticket;
    60             }
    61         }
    62     });
    63 </script>
    64 
     92<div class="buttons">
     93    <button class="signup" onclick="location.href='/signup'">Sign Up</button>
     94    <button class="login" onclick="location.href='/login'">Login</button>
     95</div>
    6596</body>
    6697</html>
Note: See TracChangeset for help on using the changeset viewer.