Changeset 950fa0d


Ignore:
Timestamp:
05/24/23 23:18:47 (18 months ago)
Author:
Gjoko Kostadinov <gjoko.kostadinov@…>
Branches:
master
Children:
77205be
Parents:
8bcd64c
Message:

Periodic update

Location:
src/main
Files:
7 added
24 edited
1 moved

Legend:

Unmodified
Added
Removed
  • src/main/java/edu/gjoko/schedlr/config/AppFilter.java

    r8bcd64c r950fa0d  
    1010import org.springframework.web.filter.GenericFilterBean;
    1111
    12 import javax.servlet.FilterChain;
    13 import javax.servlet.ServletException;
    14 import javax.servlet.ServletRequest;
    15 import javax.servlet.ServletResponse;
     12import javax.servlet.*;
    1613import javax.servlet.http.HttpServletRequest;
    1714import javax.servlet.http.HttpServletResponse;
     
    7572                            break;
    7673                    }
    77                     if(page != null && !page.trim().isEmpty()) {
     74                    if(page != null && !page.trim().isEmpty() && !DispatcherType.ERROR.equals(servletRequest.getDispatcherType())) {
    7875                        servletRequest.getRequestDispatcher(page).forward(servletRequest, servletResponse);
    7976                        return;
  • src/main/java/edu/gjoko/schedlr/config/AppSecurityConfig.java

    r8bcd64c r950fa0d  
    1010import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    1111import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    12 import org.springframework.security.config.core.GrantedAuthorityDefaults;
    1312import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    14 import org.springframework.security.web.access.AccessDeniedHandler;
    1513import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    1614import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
     15import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
     16import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
    1717import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
     18import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
     19
     20import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.*;
    1821
    1922@Configuration
     
    2124@AllArgsConstructor
    2225public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
     26
     27    private static final ClearSiteDataHeaderWriter.Directive[] SOURCE =
     28            {CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS};
    2329
    2430    private final PostgresUserDetailsService userDetailsService;
     
    5561                .defaultSuccessUrl("/homepage")
    5662                .and()
     63                .logout(logout -> logout
     64                        .logoutUrl("/logout")
     65                        .logoutSuccessUrl("/login")
     66                        .addLogoutHandler(new SecurityContextLogoutHandler())
     67                        .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(SOURCE))))
    5768                .authorizeRequests()
    5869                .antMatchers("/login").permitAll()
     70                .antMatchers("/logout").permitAll()
    5971                .antMatchers("/register_customer").permitAll()
    6072                .antMatchers("/register_business").permitAll()
    6173                .antMatchers("/api/nomenclatures/*").permitAll()
     74                .antMatchers("/api/user/me").permitAll()
    6275                .antMatchers("/api/business").permitAll()
     76                .antMatchers("/api/appointment").permitAll()
    6377                .antMatchers("/homepage").permitAll()
    6478                .antMatchers("/css/**").permitAll()
  • src/main/java/edu/gjoko/schedlr/controllers/rest/BusinessController.java

    r8bcd64c r950fa0d  
    22
    33import edu.gjoko.schedlr.entity.Business;
     4import edu.gjoko.schedlr.entity.BusinessType;
    45import edu.gjoko.schedlr.services.BusinessService;
    56import lombok.AllArgsConstructor;
    6 import org.springframework.security.core.Authentication;
    7 import org.springframework.security.core.context.SecurityContextHolder;
    87import org.springframework.web.bind.annotation.*;
    98
     
    3837        return businessService.findByOwner(businessOwnerId);
    3938    }
     39
     40    @GetMapping(path = "/{businessTypeId}")
     41    public List<Business> getBusinessesByBusinessType(@PathVariable("businessTypeId") Long id) {
     42        BusinessType businessType = new BusinessType();
     43        businessType.setId(id);
     44        return businessService.findByBusinessTypeAndActiveStatus(businessType);
     45    }
    4046}
  • src/main/java/edu/gjoko/schedlr/controllers/rest/NomenclatureController.java

    r8bcd64c r950fa0d  
    22
    33import edu.gjoko.schedlr.entity.BusinessType;
    4 import edu.gjoko.schedlr.repositories.BusinessTypeRepository;
    54import edu.gjoko.schedlr.services.NomenclaturesService;
    65import lombok.AllArgsConstructor;
     
    1413@RequestMapping("api/nomenclatures")
    1514@AllArgsConstructor
    16 public class NomenclaturesController {
     15public class NomenclatureController {
    1716
    1817    private final NomenclaturesService nomenclaturesService;
  • src/main/java/edu/gjoko/schedlr/entity/Appointment.java

    r8bcd64c r950fa0d  
    2424    private Long id;
    2525
    26     @Column(name = "start_type")
     26    @Column(name = "start_time")
    2727    private LocalDateTime startTime;
    2828
     
    3030    private LocalDateTime endTime;
    3131
    32     @Column(name = "price")
    33     private Float price;
     32    @OneToOne
     33    @JoinColumn(name = "customer_id", referencedColumnName = "id")
     34    private Stakeholder customer;
     35
     36    @ManyToOne
     37    @JoinColumn(name = "business_id")
     38    private Business business;
     39
     40    @ManyToOne
     41    @JoinColumn(name = "service_id")
     42    private Service service;
    3443
    3544    @Column(name = "created")
  • src/main/java/edu/gjoko/schedlr/entity/Business.java

    r8bcd64c r950fa0d  
    3737    private BusinessType businessType;
    3838
    39     @ManyToOne(cascade = CascadeType.PERSIST)
     39    @ManyToOne()
    4040    @JoinColumn(name = "owner_id", referencedColumnName = "id", nullable = false)
    4141    @JsonProperty("owner")
  • src/main/java/edu/gjoko/schedlr/entity/Service.java

    r8bcd64c r950fa0d  
    3333    private Integer price;
    3434
    35     @OneToOne(cascade = CascadeType.MERGE)
     35    @OneToOne(cascade = CascadeType.PERSIST)
    3636    @JoinColumn(name = "service_type_id", referencedColumnName = "id")
    3737    private ServiceType serviceType;
    3838
    3939    @ManyToOne
    40     @JoinColumn(name = "business_fk")
     40    @JoinColumn(name = "business_id")
    4141    @JsonBackReference
    4242    private Business business;
  • src/main/java/edu/gjoko/schedlr/entity/ServiceType.java

    r8bcd64c r950fa0d  
    3030    private String name;
    3131
    32 
    3332    @ManyToOne
    3433    @JoinColumn(name = "business_type_id")
  • src/main/java/edu/gjoko/schedlr/entity/Stakeholder.java

    r8bcd64c r950fa0d  
    4343
    4444    @Column(name = "password")
    45     @JsonIgnore
    4645    private String password;
    4746
  • src/main/java/edu/gjoko/schedlr/repositories/BusinessRepository.java

    r8bcd64c r950fa0d  
    33import edu.gjoko.schedlr.entity.Business;
    44import edu.gjoko.schedlr.entity.BusinessStatus;
     5import edu.gjoko.schedlr.entity.BusinessType;
    56import edu.gjoko.schedlr.entity.Stakeholder;
     7import org.hibernate.Session;
    68import org.springframework.data.jpa.repository.JpaRepository;
    79import org.springframework.stereotype.Repository;
     
    1214public interface BusinessRepository extends JpaRepository<Business, Long> {
    1315
    14     List<Business> findBusinessesByBusinessStatus(BusinessStatus status);
     16    Business findBusinessByOwner(Stakeholder owner);
    1517
    16     Business findBusinessByOwner(Stakeholder owner);
     18    List<Business> findBusinessesByBusinessTypeAndBusinessStatus(BusinessType businessType, BusinessStatus businessStatus);
    1719}
  • src/main/java/edu/gjoko/schedlr/services/BusinessService.java

    r8bcd64c r950fa0d  
    11package edu.gjoko.schedlr.services;
    22
    3 import edu.gjoko.schedlr.entity.Business;
    4 import edu.gjoko.schedlr.entity.ServiceType;
    5 import edu.gjoko.schedlr.entity.Stakeholder;
    6 import edu.gjoko.schedlr.entity.StakeholderType;
     3import edu.gjoko.schedlr.entity.*;
    74import edu.gjoko.schedlr.repositories.BusinessRepository;
     5import edu.gjoko.schedlr.repositories.ServiceRepository;
    86import edu.gjoko.schedlr.repositories.ServiceTypeRepository;
     7import edu.gjoko.schedlr.repositories.StakeholderRepository;
    98import lombok.AllArgsConstructor;
    109import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     
    1312import java.util.List;
    1413
     14import static edu.gjoko.schedlr.entity.BusinessStatus.ACTIVE;
    1515import static edu.gjoko.schedlr.entity.BusinessStatus.NEW;
    1616
     
    2121    private final BusinessRepository businessRepository;
    2222    private final ServiceTypeRepository serviceTypeRepository;
     23    private final ServiceRepository serviceRepository;
     24
     25    private final StakeholderRepository stakeholderRepository;
    2326    private BCryptPasswordEncoder bCryptPasswordEncoder;
    2427
     
    5154                .stream()
    5255                .forEach(business -> {
     56                    stakeholderRepository.save(business.getOwner());
     57                    serviceRepository.saveAll(business.getServices());
    5358                    businessRepository.save(business);
    5459                });
     
    6065        return businessRepository.findBusinessByOwner(owner);
    6166    }
     67
     68    public List<Business> findByBusinessTypeAndActiveStatus(BusinessType businessType) {
     69        return businessRepository.findBusinessesByBusinessTypeAndBusinessStatus(businessType, ACTIVE);
     70    }
    6271}
  • src/main/java/edu/gjoko/schedlr/services/PostgresUserDetailsService.java

    r8bcd64c r950fa0d  
    88import edu.gjoko.schedlr.repositories.StakeholderRepository;
    99import lombok.RequiredArgsConstructor;
    10 import org.springframework.security.access.AccessDeniedException;
    1110import org.springframework.security.core.GrantedAuthority;
    1211import org.springframework.security.core.authority.SimpleGrantedAuthority;
     
    1514import org.springframework.security.core.userdetails.UserDetailsService;
    1615import org.springframework.security.core.userdetails.UsernameNotFoundException;
    17 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    1816import org.springframework.stereotype.Service;
    1917
     
    2624
    2725    private final StakeholderRepository stakeholderRepository;
    28     private final BCryptPasswordEncoder bCryptPasswordEncoder;
    29 
    3026    private final BusinessRepository businessRepository;
    3127
     
    3329    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    3430        Stakeholder user = stakeholderRepository.findStakeholderByUsername(username);
    35         if(user == null) {
     31        if (user == null) {
    3632            throw new UsernameNotFoundException("Non existing user");
    3733        }
    3834
    39         if(user.getStakeholderType() == StakeholderType.BUSINESS_OWNER) {
     35        if (user.getStakeholderType() == StakeholderType.BUSINESS_OWNER) {
    4036            Business business = businessRepository.findBusinessByOwner(user);
    4137            if (business.getBusinessStatus() != BusinessStatus.ACTIVE) {
  • src/main/java/edu/gjoko/schedlr/services/StakeholderService.java

    r8bcd64c r950fa0d  
    2424        return stakeholderRepository.save(stakeholder);
    2525    }
     26
     27    public Stakeholder findById(Long id) {
     28        return stakeholderRepository.findById(id).get();
     29    }
    2630}
  • src/main/resources/static/css/fullcalendar.css

    r8bcd64c r950fa0d  
    135135
    136136.fc-state-highlight > div > div.fc-day-number{
    137     background-color: #ff3b30;
     137    background-color: #3b71ca;
    138138    color: #FFFFFF;
    139139    border-radius: 50%;
     
    212212
    213213.fc-state-default {
    214         border-color: #ff3b30;
    215         color: #ff3b30;
     214        border-color: #3b71ca;
     215        color: #3b71ca;
    216216}
    217217.fc-button-month.fc-state-default, .fc-button-agendaWeek.fc-state-default, .fc-button-agendaDay.fc-state-default{
     
    226226.fc-state-disabled {
    227227        color: #333333;
    228         background-color: #FFE3E3;
     228        background-color: #fff;
    229229        }
    230230
    231231.fc-state-hover {
    232         color: #ff3b30;
     232        color: #3b71ca;
    233233        text-decoration: none;
    234234        background-position: 0 -15px;
     
    241241.fc-state-down,
    242242.fc-state-active {
    243         background-color: #ff3b30;
     243        background-color: #3b71ca;
    244244        background-image: none;
    245245        outline: 0;
     
    250250        cursor: default;
    251251        background-image: none;
    252         background-color: #FFE3E3;
     252        background-color: #fff;
    253253        filter: alpha(opacity=65);
    254254        box-shadow: none;
    255         border:1px solid #FFE3E3;
    256         color: #ff3b30;
     255        border:1px solid #fff;
     256        color: #3b71ca;
    257257        }
    258258
     
    648648}
    649649.fc-week .fc-day.fc-state-highlight:hover .fc-day-number{
    650     background-color:  #ff3b30;
     650    background-color:  #3b71ca;
    651651}
    652652.fc-button-today{
  • src/main/resources/static/css/homepage.css

    r8bcd64c r950fa0d  
    11#wrap {
    2     margin-left: 50px;
    32    float:left;
     3    width: 1000px;
    44}
    55
     
    1313header {
    1414    background-color: white;
     15    height: 67px;
    1516}
    1617
     
    6566    -webkit-overflow-scrolling: touch;
    6667}
     68
     69.hidden-button {
     70    display: none;
     71    width: 0px;
     72}
     73
     74.card {
     75    padding: 10px;
     76   
     77}
  • src/main/resources/static/js/business_admin.js

    r8bcd64c r950fa0d  
    77    }).then(function (data) {
    88        business = data;
    9         console.log(business);
    109        var $header = $("#header");
    1110
     
    7473        event.preventDefault();
    7574    });
     75
     76    $("#update_services_button").click(function () {
     77        businesses = [];
     78        console.log("Gjoko");
     79        servicesObj = [];
     80        $.each($('#predefined_services_admin_panel input:checked').siblings(), function (index, label) {
     81
     82            let service = {};
     83            var id = $(label).prop('for');
     84            var text = $(label).text();
     85            var time = $($($(label).parent()).siblings()[0]).children()[0].value;
     86            var price = $($($(label).parent()).siblings()[1]).children()[0].value;
     87
     88            var serviceType = {}
     89            if (parseInt(id) != -1) {
     90                service['id'] = parseInt(id);
     91                serviceType['id'] = business['services'].find(obj => obj.id === parseInt(id))['serviceType']['id'];
     92            } else {
     93
     94            }
     95            serviceType['name'] = text.trim();
     96            service['serviceType'] = serviceType;
     97            service['duration'] = parseInt(time);
     98            service['price'] = parseInt(price);
     99            servicesObj.push(service);
     100        });
     101        business['services'] = servicesObj;
     102
     103        businesses.push(business);
     104        console.log(JSON.stringify(businesses));
     105
     106        $.ajax({
     107            url: "http://localhost:8080/api/business",
     108            type:"PATCH",
     109            data: JSON.stringify(businesses),
     110            contentType:"application/json; charset=utf-8",
     111            dataType: 'text',
     112            success: function(succ){
     113                alert( "Updates applied successfully" );
     114            },
     115            error: function(err) {
     116                alert(err);
     117            }
     118        });
     119        event.preventDefault();
     120    });
     121
     122    $("#update_owner_button").click(function() {
     123        businesses = [];
     124        console.log("Gjoko");
     125        business['owner']['firstName'] = $('#firstName').val();
     126        business['owner']['lastName'] = $('#lastName').val();
     127        business['owner']['email'] = $('#email').val();
     128        business['owner']['username'] = $('#username').val();
     129
     130        businesses.push(business);
     131        console.log(JSON.stringify(businesses));
     132
     133        $.ajax({
     134            url: "http://localhost:8080/api/business",
     135            type:"PATCH",
     136            data: JSON.stringify(businesses),
     137            contentType:"application/json; charset=utf-8",
     138            dataType: 'text',
     139            success: function(succ){
     140                alert( "Updates applied successfully" );
     141            },
     142            error: function(err) {
     143                alert(err);
     144            }
     145        });
     146    });
     147    event.preventDefault();
    76148});
  • src/main/resources/static/js/fullcalendar.js

    r8bcd64c r950fa0d  
    27552755        allDaySlot: true,
    27562756        allDayText: 'all-day',
    2757         firstHour: 6,
     2757        firstHour: 8,
     2758        lastHour: 10,
    27582759        slotMinutes: 30,
    27592760        defaultEventMinutes: 120,
     
    27672768        minTime: 0,
    27682769        maxTime: 24,
    2769         slotEventOverlap: true
     2770        slotEventOverlap: false
    27702771});
    27712772
  • src/main/resources/static/js/homepage.js

    r8bcd64c r950fa0d  
    11$(document).ready(function() {
     2    var businessTypes = {};
     3    var businesses = {};
    24    var date = new Date();
    35    var d = date.getDate();
     
    1113    */
    1214
    13 
     15    $.ajax({
     16        type: 'GET',
     17        url: "http://localhost:8080/api/user/me",
     18        success: function(data, textStatus, request) {
     19            if (data) {
     20                $('#create').parent().removeClass('hidden-button');
     21                $('#profile').parent().removeClass('hidden-button');
     22                $('#logout').parent().removeClass('hidden-button');
     23                $('#login').parent().addClass('hidden-button');
     24            } else {
     25                $('#create').parent().addClass('hidden-button');
     26                $('#profile').parent().addClass('hidden-button');
     27                $('#logout').parent().addClass('hidden-button');
     28                $('#login').parent().removeClass('hidden-button');
     29            }
     30        },
     31        error: function (request, textStatus, errorThrown) {
     32            console.log(errorThrown);
     33        }
     34    });
    1435    /* initialize the external events
    1536    -----------------------------------------------------------------*/
     
    3556    });
    3657
     58    $.ajax({
     59        url: "http://localhost:8080/api/nomenclatures/businessTypes"
     60    }).then(function (data) {
     61        businessTypes = data;
     62        var $el = $("#companyType");
     63        emptyDropdown($el);
     64
     65        $.each(data, function (index, obj) {
     66            $el.append("<option value=" + obj.value + ">" + obj.text + "</option>");
     67        });
     68    });
     69
     70    $("#companyType").change(function () {
     71        var selectedVal = $(this).find(':selected').val();
     72        var selectedObj = businessTypes[selectedVal - 1];
     73        $.ajax({
     74            url: "http://localhost:8080/api/business/" + selectedObj.value
     75        }).then(function (data) {
     76            businesses = data;
     77            console.log(data);
     78            var $el = $("#company");
     79            var $servicesEl = $("#service");
     80            emptyDropdown($el);
     81            emptyDropdown($servicesEl);
     82
     83            $.each(data, function (index, obj) {
     84                $el.append("<option value=" + obj.id + ">" + obj.companyName + "</option>");
     85            });
     86        });
     87    });
     88
     89    $("#company").change(function () {
     90        var selectedVal = $(this).find(':selected').val();
     91        $.ajax({
     92            url: "http://localhost:8080/api/appointment/business/" + selectedVal
     93        }).then(function (data) {
     94            console.log(data);
     95            var $el = $("#service");
     96            emptyDropdown($el);
     97
     98            var services = businesses.find(item => item.id == selectedVal)['services'];
     99            console.log(services);
     100
     101            $.each(services, function (index, obj) {
     102                $el.append("<option value=" + obj.id + ">" + obj.serviceType.name + "</option>");
     103            });
     104        });
     105    });
     106
    37107
    38108    /* initialize the calendar
     
    47117        editable: false,
    48118        edit: function (start, end, allDay) {
    49 
     119            console.log(start);
     120            console.log(end);
    50121        },
    51122        firstDay: 1, //  1(Monday) this can be changed to 0(Sunday) for the USA system
     
    131202                start: new Date(y, m, d, 10, 30),
    132203                allDay: false,
    133                 className: 'important'
     204                className: 'info'
    134205            },
    135206            {
     
    138209                end: new Date(y, m, d, 14, 0),
    139210                allDay: false,
    140                 className: 'important'
     211                className: 'info'
    141212            },
    142213            {
     
    155226        ],
    156227    });
    157     $("#search").click(function () {
    158         alert("qweqew");
     228
     229    $("#createAppointment").click(function() {
     230        var appointment = {};
     231        appointment['business'] = {'id': parseInt($("#company").val())};
     232        appointment['service'] = {'id': parseInt($("#service").val())};
     233        appointment['startTime'] = $("#startdatetime").val();
    159234
    160235        $.ajax({
    161             url: "http://localhost:8080/events"
    162         }).then(function(data) {
    163             console.log(data);
    164         });
    165     });
     236            url: "http://localhost:8080/api/appointment",
     237            type:"POST",
     238            data: JSON.stringify(appointment),
     239            contentType:"application/json; charset=utf-8",
     240            dataType: 'text',
     241            success: function(succ){
     242                console.log('success');
     243            },
     244            error: function(err) {
     245                console.log(JSON.stringify(err));
     246            }
     247        });
     248    })
    166249
    167250});
    168251
    169 function search() {
    170 
     252document.getElementById("login").addEventListener("click", function(event){
     253   window.location = "/login";
     254});
     255
     256function emptyDropdown(element) {
     257    var defaultOption = element.children().get(0);
     258    element.children().remove().end().append(defaultOption);
    171259}
  • src/main/resources/static/js/login.js

    r8bcd64c r950fa0d  
    11document.getElementById("login").addEventListener("click", function(event){
    2     event.preventDefault()
     2    event.preventDefault();
    33});
  • src/main/resources/static/js/register_business.js

    r8bcd64c r950fa0d  
    4949            '<div class="form-outline mb-4">' +
    5050            '    <div class="row">' +
    51             '        <div class="col-md-8">\n' +
     51            '        <div class="col-md-6">\n' +
    5252            '            <input class="form-check-input" type="checkbox" checked value="' + -1 + '" id="' + -1 + '">\n' +
    5353            '            <label class="form-check-label" for="' + -1 + '">\n' +
     
    102102        });
    103103        businessObj['services'] = servicesObj;
    104         console.log(JSON.stringify(businessObj));
    105104        $.ajax({
    106105            url: "http://localhost:8080/api/business",
  • src/main/resources/templates/admin.html

    r8bcd64c r950fa0d  
    1414<!-- Navbar start -->
    1515<header class="p-3 mb-3 border-bottom">
    16     <div class="container">
    17         <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
     16    <div class="row">
     17        <div class="col-md-10 mb-10">
    1818            Welcome to the admin page
     19        </div>
     20        <div class="col-md-2 mb-2">
     21            <button id="logout" class="btn btn-primary btn-block">
     22                Logout
     23            </button>
    1924        </div>
    2025    </div>
     
    3944
    4045    <!-- Submit button -->
    41     <button type="buttom" class="btn btn-primary btn-block mb-4" id="save_button">
     46    <button type="button" class="btn btn-primary btn-block mb-4" id="save_button">
    4247        Save changes
    4348    </button>
     
    5257<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    5358<script src="js/admin.js" type="text/javascript"></script>
     59<script src="js/logout.js" type="text/javascript"></script>
    5460</body>
    5561</html>
  • src/main/resources/templates/business_admin.html

    r8bcd64c r950fa0d  
    1414<!-- Navbar start -->
    1515<header class="p-3 mb-3 border-bottom">
    16     <div class="container">
    17         <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start" >
     16    <div class="row">
     17        <div class="col-md-10 mb-10" >
    1818            <span id="header">
    1919                Welcome back
    2020            </span>
     21        </div>
     22        <div class="col-md-2 mb-2">
     23            <button id="logout" class="btn btn-primary btn-block">
     24                Logout
     25            </button>
    2126        </div>
    2227    </div>
     
    7782                               aria-label="username"/>
    7883                    </div>
    79                     <button type="buttom" class="btn btn-primary btn-block mb-4" id="update_owner_button">
     84                    <button type="button" class="btn btn-primary btn-block mb-4" id="update_owner_button">
    8085                        Update profile
    8186                    </button>
     
    101106            </div>
    102107            <div id="predefined_services_admin_panel" class="form-outline mb-4"></div>
    103             <button type="buttom" class="btn btn-primary btn-block mb-4" id="update_services_button">
     108            <button type="button" class="btn btn-primary btn-block mb-4" id="update_services_button">
    104109                Update services
    105110            </button>
     
    112117<script src="js/business_admin.js" type="text/javascript"></script>
    113118<script src="js/bootstrap.bundle.min.js"></script>
     119<script src="js/logout.js" type="text/javascript"></script>
    114120</body>
    115121</html>
  • src/main/resources/templates/homepage.html

    r8bcd64c r950fa0d  
    2222<!-- Navbar start -->
    2323<header class="p-3 mb-3 border-bottom">
    24     <div class="container">
    25         <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
    26             <a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
    27                 <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
    28                     <use xlink:href="#bootstrap"/>
    29                 </svg>
    30             </a>
    31 
    32             <ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
    33                 <li><a href="#" class="nav-link px-2 link-secondary">Overview</a></li>
    34                 <li><a href="#" class="nav-link px-2 link-dark">Inventory</a></li>
    35                 <li><a href="#" class="nav-link px-2 link-dark">Customers</a></li>
    36                 <li><a href="#" class="nav-link px-2 link-dark">Products</a></li>
    37             </ul>
    38 
    39             <form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3" role="search">
    40                 <input type="search" class="form-control" placeholder="Search..." aria-label="Search">
    41             </form>
    42 
    43             <div class="dropdown text-end">
    44                 <a href="#" class="d-block link-dark text-decoration-none dropdown-toggle" data-bs-toggle="dropdown"
    45                    aria-expanded="false">
    46                     <img src="https://github.com/mdo.png" alt="mdo" width="32" height="32" class="rounded-circle">
    47                 </a>
    48                 <ul class="dropdown-menu text-small">
    49                     <li><a class="dropdown-item" href="#">New project...</a></li>
    50                     <li><a class="dropdown-item" href="#">Settings</a></li>
    51                     <li><a class="dropdown-item" href="#">Profile</a></li>
    52                     <li>
    53                         <hr class="dropdown-divider">
    54                     </li>
    55                     <li><a class="dropdown-item" href="#">Sign out</a></li>
    56                 </ul>
    57             </div>
     24    <div class="row" style="justify-content: space-between;">
     25        <div class="col-md-8 mb-8">
     26            Welcome to the Schedlr
     27        </div>
     28        <div class="col-md-2 mb-2">
     29            <button id="profile" class="btn btn-primary btn-block">
     30                Profile
     31            </button>
     32        </div>
     33        <div class="col-md-2 mb-2">
     34            <button id="logout" class="btn btn-primary btn-block">
     35                Logout
     36            </button>
     37        </div>
     38        <div class="col-md-2 mb-2">
     39            <button id="login" class="btn btn-primary btn-block">
     40                Login
     41            </button>
    5842        </div>
    5943    </div>
    6044</header>
    6145<!-- Navbar end -->
     46<div class="container">
     47    <div id='wrap'>
     48        <div id='calendar'></div>
     49        <div style='clear:both'></div>
     50    </div>
    6251
    63 <div id='wrap'>
    64     <div id='calendar'></div>
    65     <div style='clear:both'></div>
    66 </div>
    6752
    68 <div class="">
    6953    <div class="card">
    70         <div class="card-body py-5 px-md-5">
    71             <div>
    72                 <label for="student-birth-date">Date of search:</label>
    73                 <input type="date" id="student-birth-date"/>
    74             </div>
    75             <div>
    76                 <button type="submit" class="button" id="search">Search</button>
    77             </div>
     54        <div class="form-outline mb-4">
     55            <select class="form-select" id="companyType" aria-label="Select company type">
     56                <option disabled selected hidden>Company Type</option>
     57            </select>
     58        </div>
     59
     60        <div class="form-outline mb-4">
     61            <select class="form-select" id="company" aria-label="Select company">
     62                <option disabled selected hidden>Company</option>
     63            </select>
     64        </div>
     65        <div class="form-outline mb-4">
     66            <select class="form-select" id="service" aria-label="Select service">
     67                <option disabled selected hidden>Service</option>
     68            </select>
     69        </div>
     70        <div class="form-outline mb-4">
     71            <label for="startdatetime">Start:</label>
     72            <input type="datetime-local" id="startdatetime" name="startdatetime">
     73        </div>
     74        <div class="form-outline mb-4">
     75            <button id="createAppointment" class="btn btn-primary btn-block">
     76                Create Appointment
     77            </button>
    7878        </div>
    7979    </div>
     80
    8081</div>
    8182<script src='js/jquery-1.10.2.js' type="text/javascript"></script>
     
    8485<script src="js/homepage.js" type="text/javascript"></script>
    8586<script src="js/bootstrap.bundle.min.js"></script>
     87<script src="js/logout.js" type="text/javascript"></script>
    8688</body>
    8789</html>
  • src/main/resources/templates/login.html

    r8bcd64c r950fa0d  
    5858                            </button>
    5959                            <div th:if="${param.error}">
    60                                 <div th:if="${param.error.contains('notApproved')}" class="alert alert-danger">
     60                                <div th:if="${param.error.contains('notApproved')}" class="alert alert-danger alert-dismissible fade show">
    6161                                    Account not approved yet.
    6262                                </div>
    6363
    64                                 <div th:if="${param.error.contains('badCredentials')}" class="alert alert-danger">
     64                                <div th:if="${param.error.contains('badCredentials')}" class="alert alert-danger alert-dismissible fade show">
    6565                                    Invalid username or password.
    6666                                </div>
     67                            </div>
     68                            <div th:if="${#request.getParameter('logoutSuccessful') != null}"
     69                                 class="alert alert-success alert-dismissible fade show" role="alert">
     70                                Successful logout
    6771                            </div>
    6872                        </form>
  • src/main/resources/templates/register_business.html

    r8bcd64c r950fa0d  
    104104
    105105                            <!-- Submit button -->
    106                             <button type="buttom" class="btn btn-primary btn-block mb-4" id="signup_business_button">
     106                            <button type="button" class="btn btn-primary btn-block mb-4" id="signup_business_button">
    107107                                Sign up
    108108                            </button>
Note: See TracChangeset for help on using the changeset viewer.