mirror of
https://gitlab.com/etc404/software-engineering-project.git
synced 2026-05-10 20:52:58 +00:00
verification update
This commit is contained in:
@@ -71,10 +71,18 @@ public class SiteController {
|
||||
@GetMapping("/recipes/{id}")
|
||||
public String viewRecipe(@PathVariable Integer id, Model model, Principal principal) {
|
||||
RecipeDto recipe = recipeService.getRecipeById(id);
|
||||
|
||||
boolean saved = false;
|
||||
if (principal != null) {
|
||||
saved = userService.isFavorite(principal.getName(), id);
|
||||
}
|
||||
|
||||
model.addAttribute("recipe", recipe);
|
||||
model.addAttribute("guest", principal == null);
|
||||
model.addAttribute("saved", saved);
|
||||
|
||||
return "view-recipe";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/recipes/{id}/edit")
|
||||
public String viewEditRecipePage(@PathVariable Integer id, Model model) {
|
||||
|
||||
@@ -17,6 +17,9 @@ import com.example.demo.repository.RecipeRepo;
|
||||
import com.example.demo.repository.UserRepo;
|
||||
import com.example.demo.service.RecipeService;
|
||||
import com.example.demo.service.UserService;
|
||||
import com.example.demo.entity.Favorite;
|
||||
import com.example.demo.entity.FavoriteId;
|
||||
import com.example.demo.repository.FavoriteRepo;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
@@ -27,14 +30,16 @@ public class UserServiceImpl implements UserService {
|
||||
private RecipeRepo recipeRepository;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private RecipeService recipeService;
|
||||
private FavoriteRepo favoriteRepository;
|
||||
|
||||
public UserServiceImpl(UserRepo userRepository, RecipeRepo recipeRepository,
|
||||
PasswordEncoder passwordEncoder, RecipeService recipeService) {
|
||||
PasswordEncoder passwordEncoder, RecipeService recipeService, FavoriteRepo favoriteRepository) {
|
||||
super();
|
||||
this.userRepository = userRepository;
|
||||
this.recipeRepository = recipeRepository;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.recipeService = recipeService;
|
||||
this.favoriteRepository = favoriteRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,13 +83,16 @@ public class UserServiceImpl implements UserService {
|
||||
@Transactional
|
||||
public UserDto saveFavorite(Integer userId, Integer recipeId) {
|
||||
User existingUser = userRepository.findById(userId)
|
||||
.orElseThrow(() -> new NotFoundException("User", "id", userId));
|
||||
.orElseThrow(() -> new NotFoundException("User", "id", userId));
|
||||
|
||||
Recipe existingRecipe = recipeRepository.findById(recipeId)
|
||||
.orElseThrow(() -> new NotFoundException("Recipe", "id", recipeId));
|
||||
recipeRepository.findById(recipeId)
|
||||
.orElseThrow(() -> new NotFoundException("Recipe", "id", recipeId));
|
||||
|
||||
existingUser.getFavRecipes().add(existingRecipe);
|
||||
userRepository.save(existingUser);
|
||||
FavoriteId favoriteId = new FavoriteId(userId, recipeId);
|
||||
|
||||
if (!favoriteRepository.existsById(favoriteId)) {
|
||||
favoriteRepository.save(new Favorite(userId, recipeId));
|
||||
}
|
||||
|
||||
return convertToDto(existingUser);
|
||||
}
|
||||
@@ -112,14 +120,17 @@ public class UserServiceImpl implements UserService {
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteFavorite(Integer userId, Integer recipeId) {
|
||||
User existingUser = userRepository.findById(userId)
|
||||
.orElseThrow(() -> new NotFoundException("User", "id", userId));
|
||||
userRepository.findById(userId)
|
||||
.orElseThrow(() -> new NotFoundException("User", "id", userId));
|
||||
|
||||
Recipe existingRecipe = recipeRepository.findById(recipeId)
|
||||
.orElseThrow(() -> new NotFoundException("Recipe", "id", recipeId));
|
||||
recipeRepository.findById(recipeId)
|
||||
.orElseThrow(() -> new NotFoundException("Recipe", "id", recipeId));
|
||||
|
||||
existingUser.getFavRecipes().remove(existingRecipe);
|
||||
userRepository.save(existingUser);
|
||||
FavoriteId favoriteId = new FavoriteId(userId, recipeId);
|
||||
|
||||
if (favoriteRepository.existsById(favoriteId)) {
|
||||
favoriteRepository.deleteById(favoriteId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -235,4 +246,13 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
return favoriteDtos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean isFavorite(String username, Integer recipeId) {
|
||||
User user = userRepository.findByUsername(username)
|
||||
.orElseThrow(() -> new NotFoundException("User", "username", username));
|
||||
|
||||
return favoriteRepository.existsById(new FavoriteId(user.getId(), recipeId));
|
||||
}
|
||||
}
|
||||
@@ -42,4 +42,6 @@ public interface UserService {
|
||||
ProfileDto updateProfile(String username, UpdateProfileDto dto);
|
||||
|
||||
List<RecipeDto> getFavoriteRecipesByUsername(String username);
|
||||
|
||||
boolean isFavorite(String username, Integer recipeId);
|
||||
}
|
||||
@@ -40,7 +40,7 @@
|
||||
<button onclick="verifyOtp()">Verify</button>
|
||||
|
||||
<p class="resend-text">
|
||||
Didn’t get the code?
|
||||
Didn’t get the code? Check your spam folder or wait a minute and try again.
|
||||
<button id="resendBtn" onclick="resendOtp()" disabled>
|
||||
Resend code (60s)
|
||||
</button>
|
||||
|
||||
@@ -119,7 +119,13 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button type="button" class="save-btn" th:data-recipe-id="${recipe.id}">Save Recipe</button>
|
||||
<button type="button"
|
||||
class="save-btn"
|
||||
th:data-recipe-id="${recipe.id}"
|
||||
th:data-saved="${saved}"
|
||||
th:text="${saved} ? 'Remove Saved Recipe' : 'Save Recipe'">
|
||||
Save Recipe
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div th:unless="${recipe != null}" class="recipe-not-found">
|
||||
@@ -131,55 +137,57 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function getCurrentUser() {
|
||||
const response = await fetch('/api/users/me', {
|
||||
credentials: 'same-origin'
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const user = await response.json();
|
||||
return user || null;
|
||||
}
|
||||
|
||||
async function saveRecipe(recipeId, button) {
|
||||
const csrfHeader = document.querySelector('meta[name="_csrf_header"]')?.content;
|
||||
const csrfToken = document.querySelector('meta[name="_csrf"]')?.content;
|
||||
|
||||
const user = await getCurrentUser();
|
||||
|
||||
if (!user || !user.id) {
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/users/${user.id}/favorites/${recipeId}`, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
...(csrfHeader && csrfToken ? { [csrfHeader]: csrfToken } : {})
|
||||
async function getCurrentUser() {
|
||||
const response = await fetch('/api/users/me', {
|
||||
credentials: 'same-origin'
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
alert(text || 'Could not save recipe.');
|
||||
return;
|
||||
|
||||
const user = await response.json();
|
||||
return user || null;
|
||||
}
|
||||
|
||||
button.textContent = 'Saved';
|
||||
button.disabled = true;
|
||||
}
|
||||
|
||||
document.querySelectorAll('.save-btn').forEach(button => {
|
||||
button.addEventListener('click', async () => {
|
||||
const recipeId = button.dataset.recipeId;
|
||||
await saveRecipe(recipeId, button);
|
||||
|
||||
async function toggleSaveRecipe(recipeId, button) {
|
||||
const csrfHeader = document.querySelector('meta[name="_csrf_header"]')?.content;
|
||||
const csrfToken = document.querySelector('meta[name="_csrf"]')?.content;
|
||||
|
||||
const user = await getCurrentUser();
|
||||
|
||||
if (!user || !user.id) {
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
const isSaved = button.dataset.saved === 'true';
|
||||
|
||||
const response = await fetch(`/api/users/${user.id}/favorites/${recipeId}`, {
|
||||
method: isSaved ? 'DELETE' : 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
...(csrfHeader && csrfToken ? { [csrfHeader]: csrfToken } : {})
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
alert(text || 'Could not update saved recipe.');
|
||||
return;
|
||||
}
|
||||
|
||||
button.dataset.saved = isSaved ? 'false' : 'true';
|
||||
button.textContent = isSaved ? 'Save Recipe' : 'Un-save Recipe';
|
||||
}
|
||||
|
||||
document.querySelectorAll('.save-btn').forEach(button => {
|
||||
button.addEventListener('click', async () => {
|
||||
const recipeId = button.dataset.recipeId;
|
||||
await toggleSaveRecipe(recipeId, button);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user