Skip to content
Snippets Groups Projects
Commit e9251e12 authored by Richard Githuba's avatar Richard Githuba
Browse files

Merge branch...

Merge branch '235-as-a-user-i-want-to-be-able-to-reach-out-to-the-community-team-with-questions-or-feedback-so' into 'release/Sprint-4'

Resolve "As a user, I want to be able to reach out to the community team with questions or feedback, so that I can get the information I need or share my thoughts with the team."

See merge request c24108486/team-11-polish-community-group!50
parents 70c5bbcf 3fcc9f89
No related branches found
No related tags found
No related merge requests found
package polish_community_group_11.polish_community.contact.Controllers;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.stereotype.Controller;
@Controller
public class Contact {
@GetMapping("/contactus")
public ModelAndView home(){
ModelAndView modelAndView = new ModelAndView("contact/contact");
return modelAndView;
}
}
/* General Styles */
body {
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: #f4f4f9;
font-family: Arial, sans-serif;
padding-top: 80px;
}
#title{
color: black;
text-align: center;
font-size: 35px;
margin-bottom: 30px;
font-weight: bold;
}
#contact-form {
margin: 20px auto;
max-width: 900px;
border-radius: 10px;
background-color: transparent;
}
/* FAQ Section */
#faq {
padding: 20px;
}
.faq-question {
cursor: pointer;
font-weight: bold;
color: #333;
}
.faq-question:hover {
color: #4CAF50;
}
.faq-answer {
display: none;
color: #666;
padding-left: 20px;
}
#map {
display: none;
}
#contact-form {
display: flex;
justify-content: space-between;
align-items: flex-start;
text-align: left;
margin-top: 20px;
gap: 30px;
}
#contact-form-container {
width: 50%;
padding: 30px;
background-color: transparent;
border: 1px solid #ddd;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
#contact-form-container h3 {
margin-bottom: 20px;
color: #333;
}
#contact-info-container {
width: 50%;
padding: 30px;
background-color: transparent;
border: 1px solid #ddd;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
#contact-info-container h3 {
margin-bottom: 20px;
color: #333;
}
#contactForm label {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: #333;
}
#contactForm input, #contactForm textarea {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
font-size: 16px;
color: #333;
}
#contactForm input:focus, #contactForm textarea:focus {
border-color: #007BFF;
outline: none;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
}
#contactForm button {
display: inline-block;
padding: 10px 20px;
font-size: 16px;
color: #fff;
background-color: black;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
#contactForm button:hover {
background-color: #333;
}
#formFeedback {
margin: 10px;
font-size: 14px;
color: grey;
}
body, .faq-answer, #contactForm input, #contactForm textarea {
font-size: 14px;
color: #666;
}
h2, h3, .faq-question {
color: #333;
}
/* Media Queries for Mobile Optimization */
@media (max-width: 768px) {
/* Stack Contact Form and Contact Info Vertically on Smaller Screens */
#contact-form {
flex-direction: column;
}
#contact-form-container, #contact-info-container {
width: 100%;
margin-bottom: 20px;
}
}
@media (max-width: 480px) {
#faq h2 {
font-size: 20px;
}
#contact-form h2 {
font-size: 18px;
}
.faq-question {
font-size: 16px;
}
#contact-form input, #contact-form textarea {
font-size: 14px;
}
#contact-form button {
font-size: 14px;
}
}
// initalise the chart when the page loads, could also initialize map but didn't work like the chart did
// also sort out the animations of the contact form
document.addEventListener('DOMContentLoaded', () => {
// call the chart initialization method
initUserChart();
// input focus and blur animation for the text
document.querySelectorAll('input, textarea').forEach(field => {
field.addEventListener('focus', () => {
anime({
targets: field,
scale: 1.05, // enlarge teh box slightly on focus
duration: 300,
easing: 'easeInOutQuad'
});
});
field.addEventListener('blur', () => {
anime({
targets: field,
scale: 1, // return the box to the original size
duration: 300,
easing: 'easeInOutQuad'
});
});
});
// submit button hover bounce effect
const submitButton = document.getElementById('submitButton');
submitButton.addEventListener('mouseover', () => {
anime({
targets: submitButton,
translateY: [-10, 0],
duration: 500,
easing: 'easeOutBounce'
});
});
// FAQ functionality that includes the map initialization
document.querySelectorAll('.faq-question').forEach(question => {
question.addEventListener('click', function () {
// answer of the questions
const answer = this.nextElementSibling;
// the map element
const mapContainer = this.nextElementSibling.nextElementSibling;
// toggle visibility of the answer (block = visible, none = hidden)
const isHidden = answer.style.display === 'none' || answer.style.display === '';
answer.style.display = isHidden ? 'block' : 'none';
// if the map container is hidden, initialize the map
if (mapContainer.style.display === 'none' || mapContainer.style.display === '') {
// show the map
mapContainer.style.display = 'block';
// call the map initialization method
initMap(mapContainer);
} else {
// hide the map
mapContainer.style.display = 'none';
}
});
});
// form submission that displays a feedback message
document.getElementById('contactForm').addEventListener('submit', function (event) {
event.preventDefault();
// get all the inputs from the fields
const name = document.getElementById('name').value.trim();
const email = document.getElementById('email').value.trim();
const message = document.getElementById('message').value.trim();
// get the feedback element and clear the previous feedback
const feedback = document.getElementById('formFeedback');
feedback.textContent = '';
feedback.style.color = '';
let isValid = true;
// check for empty fields
if (!name || !email || !message) {
feedback.textContent = 'Please fill out all fields.';
feedback.style.color = 'red';
isValid = false;
}
// check for valid email
if (email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
feedback.textContent = 'Please enter a valid email address.';
feedback.style.color = 'red';
isValid = false;
}
}
// if everything is valid
if (isValid) {
feedback.textContent = 'Thank you for your message! We will get back to you within 2-3 days.';
feedback.style.color = 'green';
// reset the form fields
this.reset();
}
});
});
// funtion for initialising the map
function initMap(container) {
// using Cardiff location coordinates
const location = { lat: 51.4778, lng: -3.1776 };
// create the map that centers at Cardiff
const map = new google.maps.Map(container, {
zoom: 12,
center: location
});
// add the marker that is placed at Cardiff
const marker = new google.maps.Marker({
position: location,
map: map,
title: "Our Location",
});
}
// funtion for initialising the chart
function initUserChart() {
// get the html chart
const ctx = document.getElementById('userChart').getContext('2d');
// mock data for years and the corresponding number of users
// in future versions, this would collect data from the users database
const years = [2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024];
const numberOfUsers = [500, 700, 900, 1200, 1500, 2000, 2500, 3000, 4000, 5000, 6000];
// set up the chart
new Chart("userChart", {
type: "line", // line chart
data: {
labels: years,
datasets: [{
label: "Number of Users",
backgroundColor: "rgba(0,0,255,0.2)",
borderColor: "rgba(0,0,255,1.0)",
data: numberOfUsers,
fill: true, // fill the area below the line
}]
},
// styling options for the chart
options: {
scales: {
x: {
title: {
display: true,
text: 'Number of Users'
},
beginAtZero: true,
},
y: {
title: {
display: true,
text: 'Year'
}
}
},
responsive: true,
}
});
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact Us</title>
<link rel="stylesheet" href="/css/contact/contact.css">
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAcnCewJfgcEPXtBPkokQwJXcOwUy-9iwI&callback=initMap" async defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</head>
<body layout:fragment="content">
<h1 id="title">Contact Us</h1>
<!-- Contact Form Section -->
<section id="contact-form">
<!-- Contact Form Container -->
<div id="contact-form-container">
<h2>Get in Touch</h2>
<form id="contactForm" action="/submit" method="POST" novalidate>
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<label for="message">Message:</label>
<textarea id="message" name="message"></textarea>
<div id="formFeedback"></div>
<button type="submit" id="submitButton">Submit</button>
</form>
</div>
<!-- Contact Information Container -->
<div id="contact-info-container">
<h3>Contact Information</h3>
<p><strong>Phone:</strong> +123456789</p>
<p><strong>Email:</strong> contact@domain.com</p>
<p><strong>Address:</strong> 123 Street, City, Country</p>
<a href="https://www.facebook.com/LudekPCG" class="social-icon"><img src="/assets/navbarImages/facebook.png" alt="Facebook"></a>
<a href="#" class="social-icon"><img src="/assets/navbarImages/twitter.png" alt="Twitter"></a>
<a href="#" class="social-icon"><img src="/assets/navbarImages/instagram.png" alt="Instagram"></a>
</div>
</section>
<!-- FAQ Section -->
<section id="faq">
<h2>Frequently Asked Questions</h2>
<div class="faq-item">
<h3 class="faq-question">What is the community?</h3>
<p class="faq-answer">Our community is a group of people who support and connect with each other.</p>
</div>
<div class="faq-item">
<h3 class="faq-question">How can I join the community?</h3>
<p class="faq-answer">You can join by signing up through the main page or by contacting us directly.</p>
</div>
<div class="faq-item">
<h3 class="faq-question">How do I contact support?</h3>
<p class="faq-answer">You can reach out to us through the contact form above.</p>
</div>
<div class="faq-item">
<h3 class="faq-question">How many users are currently on the platform?</h3>
<div class="faq-answer">
<canvas id="userChart" width="400" height="200"></canvas> <!-- The canvas for the chart -->
</div>
</div>
<div class="faq-item">
<h3 class="faq-question">Where are you located?</h3>
<p class="faq-answer">We are located in the heart of the city. You can find us on the map below!</p>
<!-- Interactive Map -->
<div id="map" style="height: 400px;"></div> <!-- Map container -->
</div>
</section>
<script src="/js/contact/contact.js"></script>
</body>
</html>
package polish_community_group_11.polish_community.register; package polish_community_group_11.polish_community.register;
import polish_community_group_11.polish_community.register.dao.UserRepository; import polish_community_group_11.polish_community.register.dao.UserRepository;
import polish_community_group_11.polish_community.register.services.UserServiceImpl; // Assuming UserServiceImpl is the correct implementation
import polish_community_group_11.polish_community.register.models.User; import polish_community_group_11.polish_community.register.models.User;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks; import static org.junit.jupiter.api.Assertions.*;
import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired;
import org.mockito.MockitoAnnotations; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.time.LocalDate; import java.time.LocalDate;
import static org.mockito.Mockito.*; import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import java.util.Arrays;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
@SpringBootTest
@Transactional
public class RegisterTest { public class RegisterTest {
@Mock @Autowired
private UserRepository userRepository; // Mocking the UserRepository private UserRepository userRepository;
@BeforeEach
public void setUp() {
// Create and save 3 users to the database before each test
User user1 = new User();
user1.setEmail("user1@example.com");
user1.setPassword("password1");
user1.setFullname("User One");
user1.setDateOfBirth(LocalDate.of(2003, 1, 1));
user1.setRoleId(1);
userRepository.saveUser(user1);
@InjectMocks User user2 = new User();
private UserServiceImpl userService; // Injecting mock into the service user2.setEmail("user2@example.com");
user2.setPassword("password2");
user2.setFullname("User Two");
user2.setDateOfBirth(LocalDate.of(2003, 2, 2));
user2.setRoleId(2);
userRepository.saveUser(user2);
User user3 = new User();
user3.setEmail("user3@example.com");
user3.setPassword("password3");
user3.setFullname("User Three");
user3.setDateOfBirth(LocalDate.of(2003, 3, 3));
user3.setRoleId(1);
userRepository.saveUser(user3);
System.out.println("3 users have been saved to the database.");
}
@Test @Test
public void testFindAllUsers() { public void testSaveUser() {
System.out.println("Starting testFindAllUsers..."); // create a new user
// Arrange: Create a mock user using setters User newUser = new User();
List<User> mockUsers = new ArrayList<>(); newUser.setEmail("newuser@example.com");
User user = new User(); newUser.setFullname("New User");
user.setId(1); newUser.setPassword("password4");
user.setEmail("test@example.com"); newUser.setDateOfBirth(LocalDate.of(2000, 1, 1));
user.setPassword("password"); newUser.setRoleId(1);
user.setFullname("John Doe");
user.setDateOfBirth(LocalDate.of(1990, 1, 1)); // call the saveUser method from the repository
user.setRoleId(1); int userId = userRepository.saveUser(newUser);
// print out the saved user's ID
System.out.println("Saved user ID: " + userId);
// verify that the returned user ID is greater than 0, meaning the user was saved
assertTrue(userId > 0, "User ID is greater than 0 therefore it was a successful insert");
mockUsers.add(user); }
// Mock the findAllUsers method to return the mock users
when(userRepository.findAllUsers()).thenReturn(mockUsers); @Test
public void testFindAllUsers() {
// Act: Call the service method // call the repository method to retrieve all users
List<User> users = userService.findAllUsers(); List<User> users = userRepository.findAllUsers();
System.out.println("Returned users: " + users);
// print out all users
// Assert: Verify that the result is not null, contains the expected users, and is not empty System.out.println("Users list:");
for (User user : users) {
System.out.println(user.getFullname() + " - " + user.getEmail());
}
// verify that the result is not null and contains the expected number of users
assertNotNull(users); assertNotNull(users);
assertFalse(users.isEmpty()); assertEquals(4, users.size());
assertEquals(1, users.size()); // Expecting 1 user
// verify that the users have the correct details
for (User user : users) {
assertNotNull(user.getEmail());
assertNotNull(user.getFullname());
}
System.out.println("Test completed: Found " + users.size() + " users.");
}
@Test
public void testFindByEmail() {
// intialiaze the testing emails
List<String> emails = Arrays.asList("user1@example.com", "user2@example.com", "user3@example.com");
// loop through each email
for (String email : emails) {
// call the repository method to retrieve user by email
User userByEmail = userRepository.findByEmail(email);
if (userByEmail != null) {
System.out.println("User found by email: " + userByEmail.getFullname() + " - " + userByEmail.getEmail());
} else {
System.out.println("No user found with the email " + email);
}
// verify that the user is returned
assertNotNull(userByEmail);
assertEquals(email, userByEmail.getEmail());
}
System.out.println("Test completed: Found 3 users");
User wrongUser = userRepository.findByEmail("nonexistent@example.com");
System.out.println("Test completed successfully. Found " + users.size() + " users."); // ensure that no user is found when
assertNull(wrongUser);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment