mirror of
https://github.com/LOBSTERVOVA/Tennis-Site.git
synced 2026-04-17 17:40:49 +03:00
начало разработки страницы профиля
This commit is contained in:
@@ -50,12 +50,14 @@ public class SecurityConfig {
|
||||
.addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION)
|
||||
//.addFilterAfter(errorHandlingFilter, SecurityWebFiltersOrder.AUTHENTICATION)
|
||||
.authorizeExchange(exchange -> exchange
|
||||
.pathMatchers("/account/login","/error","/error/**").permitAll()
|
||||
.pathMatchers("/account/login","/error","/error/**", "/account/logout").permitAll()
|
||||
.pathMatchers("/account/**").authenticated()
|
||||
.anyExchange().permitAll()
|
||||
)
|
||||
.formLogin(loginSpec -> loginSpec.loginPage("/account/login").authenticationSuccessHandler(authenticationSuccessHandler()))
|
||||
.logout(logoutSpec -> logoutSpec.logoutSuccessHandler(logoutSuccessHandler()))
|
||||
.logout(logoutSpec -> logoutSpec
|
||||
.logoutUrl("/account/logout") // ← URL для логаута
|
||||
.logoutSuccessHandler(logoutSuccessHandler()))
|
||||
.requestCache(requestCacheSpec -> requestCacheSpec.requestCache(serverRequestCache()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.example.dateplanner.controllers.web;
|
||||
|
||||
import ch.qos.logback.core.model.Model;
|
||||
import com.example.dateplanner.models.entities.AppUser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -20,4 +21,15 @@ import java.util.Map;
|
||||
@RequestMapping("/account")
|
||||
public class AccountController {
|
||||
|
||||
@GetMapping("/profile")
|
||||
public Mono<Rendering> profile() {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put("title", "Profile");
|
||||
model.put("index", "profile");
|
||||
return Mono.just(
|
||||
Rendering.view("template")
|
||||
.model(model)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Merriweather:ital,opsz,wght@0,18..144,300..900;1,18..144,300..900&display=swap');
|
||||
|
||||
body {
|
||||
font-family: "Roboto Condensed", sans-serif !important;
|
||||
font-family: 'Segoe UI', system-ui, sans-serif !important;
|
||||
font-optical-sizing: auto !important;
|
||||
font-weight: 400 !important;
|
||||
font-style: normal !important;
|
||||
|
||||
81
src/main/resources/static/css/profile.css
Normal file
81
src/main/resources/static/css/profile.css
Normal file
@@ -0,0 +1,81 @@
|
||||
.sidebar {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 25px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
|
||||
position: sticky;
|
||||
top: 30px;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.profile-main-content {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.profile-user-avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
border: 5px solid white;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.match-badge {
|
||||
background: linear-gradient(45deg, #E74C3CFF, #FD79A8FF);
|
||||
color: white;
|
||||
padding: 5px 15px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.profile-completion {
|
||||
background: #F9F7F7FF;
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.completion-percentage {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: #E74C3CFF;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 10px !important;
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background-color: #E74C3CFF !important;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.profile-nav-link-custom {
|
||||
color: #2D3436FF;
|
||||
padding: 15px 20px;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 10px;
|
||||
transition: all 0.3s;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.profile-nav-link-custom:hover {
|
||||
background: rgba(231, 76, 60, 0.1) !important;
|
||||
color: #E74C3CFF !important;
|
||||
transform: translateX(5px) !important;
|
||||
}
|
||||
|
||||
.profile-nav-link-custom.active {
|
||||
background: rgba(231, 76, 60, 0.1) !important;
|
||||
color: #E74C3CFF !important;
|
||||
border-left: 4px solid #E74C3CFF !important;
|
||||
}
|
||||
@@ -2,3 +2,4 @@
|
||||
@import "main.css";
|
||||
@import "header.css";
|
||||
@import "places.css";
|
||||
@import "profile.css";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
function initHeader($header){
|
||||
console.log("init header date")
|
||||
|
||||
let authSection
|
||||
if(!auth) {
|
||||
authSection = `
|
||||
@@ -15,18 +16,20 @@ function initHeader($header){
|
||||
<div id="userProfileContainer" class="dropdown ms-0 ms-lg-3 mt-2 mt-lg-0">
|
||||
<a href="#" class="d-flex align-items-center text-decoration-none dropdown-toggle"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<div class="user-avatar" id="userAvatar">А</div>
|
||||
<span class="ms-2 d-md-inline" id="userName">Алексей</span>
|
||||
<div class="user-avatar" id="userAvatar">${user.firstName.charAt(0)}${user.lastName.charAt(0)}</div>
|
||||
<span class="ms-2 d-md-inline" id="userName">${user.firstName}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li>
|
||||
<div class="user-info">
|
||||
<div class="user-avatar" id="dropdownUserAvatar">А</div>
|
||||
<div class="user-details">
|
||||
<h6 id="dropdownUserName">Алексей Петров</h6>
|
||||
<small id="dropdownUserEmail">alexey@example.com</small>
|
||||
<a href="/account/profile" class="text-decoration-none text-black">
|
||||
<div class="user-info">
|
||||
<div class="user-avatar" id="dropdownUserAvatar">${user.firstName.charAt(0)}${user.lastName.charAt(0)}</div>
|
||||
<div class="user-details">
|
||||
<h6 id="dropdownUserName">${user.firstName} ${user.lastName}</h6>
|
||||
<small id="dropdownUserEmail">${user.phone}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="#"><i class="fas fa-heart"></i> Мои избранные</a></li>
|
||||
@@ -36,7 +39,14 @@ function initHeader($header){
|
||||
<li><a class="dropdown-item" href="#" onclick="showAddPlaceModal()"><i class="fas fa-plus-circle"></i> Добавить место</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="#"><i class="fas fa-cog"></i> Настройки</a></li>
|
||||
<li><a class="dropdown-item text-danger" href="#" onclick="logout()"><i class="fas fa-sign-out-alt"></i> Выйти</a></li>
|
||||
<li>
|
||||
<form action="/account/logout" method="post" style="display: inline;">
|
||||
<input type="hidden" name="_csrf" value="${csrf.token}"/>
|
||||
<button type="submit" class="dropdown-item text-danger" style="border: none; background: none; width: 100%; text-align: left;">
|
||||
<i class="fas fa-sign-out-alt"></i> Выйти
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
@@ -179,4 +189,4 @@ function initHeader($header){
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
1338
src/main/resources/templates/all-profile.html
Normal file
1338
src/main/resources/templates/all-profile.html
Normal file
File diff suppressed because it is too large
Load Diff
85
src/main/resources/templates/pages/profile.html
Normal file
85
src/main/resources/templates/pages/profile.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<div class="container py-5" id="mainPageContainer">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 mb-4">
|
||||
<div class="sidebar">
|
||||
<div class="text-center">
|
||||
<img src="https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80"
|
||||
class="profile-user-avatar" alt="Анна">
|
||||
<h4 class="mb-1">Анна, 26</h4>
|
||||
<p class="text-muted mb-3">Москва</p>
|
||||
<div class="match-badge">Профиль на 85%</div>
|
||||
</div>
|
||||
|
||||
<div class="profile-completion">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span>Заполненность профиля:</span>
|
||||
<span class="completion-percentage">85%</span>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 85%"></div>
|
||||
</div>
|
||||
<p class="small text-muted mt-2 mb-0">Полный профиль привлекает на 60% больше откликов</p>
|
||||
</div>
|
||||
|
||||
<nav class="nav flex-column" id="profile-sections-navigator">
|
||||
<a class="profile-nav-link-custom active" data-section="profileSection" href="#"
|
||||
onclick="showSection('profile')">
|
||||
<i class="fas fa-user me-3"></i>Мой профиль
|
||||
</a>
|
||||
<a class="profile-nav-link-custom" data-section="proposalsSection" href="#"
|
||||
onclick="showSection('proposals')">
|
||||
<i class="fas fa-heart me-3"></i>Мои предложения
|
||||
<span class="notification-badge">3</span>
|
||||
</a>
|
||||
<a class="profile-nav-link-custom" data-section="organizationsSection" href="#"
|
||||
onclick="showSection('organizations')">
|
||||
<i class="fas fa-building me-3"></i>Мои организации
|
||||
</a>
|
||||
<a class="profile-nav-link-custom" data-section="eventsSection" href="#"
|
||||
onclick="showSection('events')">
|
||||
<i class="fas fa-calendar-alt me-3"></i>Мероприятия
|
||||
</a>
|
||||
<a class="profile-nav-link-custom" data-section="settingsSection" href="#"
|
||||
onclick="showSection('settings')">
|
||||
<i class="fas fa-cog me-3"></i>Настройки
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div class="mt-4">
|
||||
<button class="btn btn-heart w-100" onclick="createNewProposal()">
|
||||
<i class="fas fa-plus me-2"></i>Предложить свидание
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<div class="profile-main-content">
|
||||
<div class="section-content d-block" id="profileSection">
|
||||
1
|
||||
</div>
|
||||
<div class="section-content d-none" id="proposalsSection">
|
||||
2
|
||||
</div>
|
||||
<div class="section-content d-none" id="organizationsSection">
|
||||
3
|
||||
</div>
|
||||
<div class="section-content d-none" id="eventsSection">
|
||||
4
|
||||
</div>
|
||||
<div class="section-content d-none" id="settingsSection">
|
||||
5
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$('#profile-sections-navigator').on('click', '.profile-nav-link-custom', function () {
|
||||
$('#profile-sections-navigator').find('.profile-nav-link-custom').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
const selectedSectionId = $(this).data('section');
|
||||
console.log(selectedSectionId);
|
||||
$('.section-content').removeClass('d-block').addClass('d-none');
|
||||
$(`#${selectedSectionId}`).removeClass('d-none').addClass('d-block');
|
||||
})
|
||||
</script>
|
||||
@@ -26,6 +26,7 @@
|
||||
<header th:insert="~{blocks/header}" style="margin-bottom: 64px"></header>
|
||||
|
||||
<main th:if="${index} == 'home'" th:insert="~{pages/home}"></main>
|
||||
<main th:if="${index} == 'profile'" th:insert="~{pages/profile}"></main>
|
||||
|
||||
<footer class="mt-auto" th:insert="~{blocks/footer}"></footer>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user