generated from nhcarrigan/template
feat: ability to edit suggestions when accepting
This commit is contained in:
@@ -227,6 +227,166 @@ import { Suggestion, SuggestionStatus, SuggestionEntity } from '@library/shared-
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (showEditModal()) {
|
||||
<div class="modal-overlay" (click)="closeEditModal()">
|
||||
<div class="modal edit-modal" (click)="$event.stopPropagation()">
|
||||
<h3>Review & Edit Before Accepting</h3>
|
||||
<p>Review and edit the details before adding to your collection.</p>
|
||||
|
||||
@if (editingSuggestion()) {
|
||||
<form (ngSubmit)="confirmAcceptWithEdits()">
|
||||
<div class="form-group">
|
||||
<label for="edit-title">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-title"
|
||||
[(ngModel)]="editedData.title"
|
||||
name="title"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
@switch (editingSuggestion()!.entityType) {
|
||||
@case ('BOOK') {
|
||||
<div class="form-group">
|
||||
<label for="edit-author">Author</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-author"
|
||||
[(ngModel)]="editedData.author"
|
||||
name="author"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit-isbn">ISBN</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-isbn"
|
||||
[(ngModel)]="editedData.isbn"
|
||||
name="isbn"
|
||||
>
|
||||
</div>
|
||||
}
|
||||
@case ('GAME') {
|
||||
<div class="form-group">
|
||||
<label for="edit-platform">Platform</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-platform"
|
||||
[(ngModel)]="editedData.platform"
|
||||
name="platform"
|
||||
>
|
||||
</div>
|
||||
}
|
||||
@case ('MUSIC') {
|
||||
<div class="form-group">
|
||||
<label for="edit-artist">Artist</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-artist"
|
||||
[(ngModel)]="editedData.artist"
|
||||
name="artist"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit-type">Type</label>
|
||||
<select id="edit-type" [(ngModel)]="editedData.type" name="type" required>
|
||||
<option value="ALBUM">Album</option>
|
||||
<option value="SINGLE">Single</option>
|
||||
<option value="EP">EP</option>
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
@case ('ART') {
|
||||
<div class="form-group">
|
||||
<label for="edit-artist">Artist</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-artist"
|
||||
[(ngModel)]="editedData.artist"
|
||||
name="artist"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit-description">Description</label>
|
||||
<textarea
|
||||
id="edit-description"
|
||||
[(ngModel)]="editedData.description"
|
||||
name="description"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit-imageUrl">Image URL</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-imageUrl"
|
||||
[(ngModel)]="editedData.imageUrl"
|
||||
name="imageUrl"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
}
|
||||
@case ('SHOW') {
|
||||
<div class="form-group">
|
||||
<label for="edit-type">Type</label>
|
||||
<select id="edit-type" [(ngModel)]="editedData.type" name="type" required>
|
||||
<option value="TV_SERIES">TV Series</option>
|
||||
<option value="ANIME">Anime</option>
|
||||
<option value="FILM">Film</option>
|
||||
<option value="DOCUMENTARY">Documentary</option>
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
@case ('MANGA') {
|
||||
<div class="form-group">
|
||||
<label for="edit-author">Author</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-author"
|
||||
[(ngModel)]="editedData.author"
|
||||
name="author"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-notes">Notes</label>
|
||||
<textarea
|
||||
id="edit-notes"
|
||||
[(ngModel)]="editedData.notes"
|
||||
name="notes"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
@if (editingSuggestion()!.entityType !== 'ART') {
|
||||
<div class="form-group">
|
||||
<label for="edit-coverImage">Cover Image URL</label>
|
||||
<input
|
||||
type="text"
|
||||
id="edit-coverImage"
|
||||
[(ngModel)]="editedData.coverImage"
|
||||
name="coverImage"
|
||||
>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="modal-actions">
|
||||
<button type="submit" class="btn btn-accept">Accept with Edits</button>
|
||||
<button type="button" (click)="closeEditModal()" class="btn btn-secondary">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
@@ -503,6 +663,14 @@ import { Suggestion, SuggestionStatus, SuggestionEntity } from '@library/shared-
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.edit-modal {
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
.edit-modal form {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.modal h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
}
|
||||
@@ -549,6 +717,11 @@ export class AdminSuggestionsComponent implements OnInit {
|
||||
decliningsuggestion = signal<Suggestion | null>(null);
|
||||
declineReason = '';
|
||||
|
||||
// Edit modal state
|
||||
showEditModal = signal(false);
|
||||
editingSuggestion = signal<Suggestion | null>(null);
|
||||
editedData: any = {};
|
||||
|
||||
// Pagination state
|
||||
currentPage = signal(1);
|
||||
pageSize = signal(25);
|
||||
@@ -637,15 +810,59 @@ export class AdminSuggestionsComponent implements OnInit {
|
||||
}
|
||||
|
||||
async acceptSuggestion(suggestion: Suggestion) {
|
||||
if (!confirm(`Accept "${suggestion.title}"? This will add it to your collection.`)) return;
|
||||
this.editingSuggestion.set(suggestion);
|
||||
|
||||
try {
|
||||
await this.suggestionService.acceptSuggestion(suggestion.id);
|
||||
alert(`"${suggestion.title}" has been added to your collection!`);
|
||||
this.loadSuggestions();
|
||||
} catch {
|
||||
alert('Failed to accept suggestion. Please try again.');
|
||||
// Pre-populate the edit form with suggestion data
|
||||
this.editedData = {
|
||||
title: suggestion.title,
|
||||
notes: '',
|
||||
coverImage: '',
|
||||
coverArt: ''
|
||||
};
|
||||
|
||||
// Add entity-specific data
|
||||
switch (suggestion.entityType) {
|
||||
case 'BOOK':
|
||||
const bookData = suggestion.bookData as any;
|
||||
this.editedData.author = bookData?.author || '';
|
||||
this.editedData.isbn = bookData?.isbn || '';
|
||||
this.editedData.notes = bookData?.notes || '';
|
||||
this.editedData.coverImage = bookData?.coverImage || '';
|
||||
break;
|
||||
case 'GAME':
|
||||
const gameData = suggestion.gameData as any;
|
||||
this.editedData.platform = gameData?.platform || '';
|
||||
this.editedData.notes = gameData?.notes || '';
|
||||
this.editedData.coverImage = gameData?.coverImage || '';
|
||||
break;
|
||||
case 'MUSIC':
|
||||
const musicData = suggestion.musicData as any;
|
||||
this.editedData.artist = musicData?.artist || '';
|
||||
this.editedData.type = musicData?.type || 'ALBUM';
|
||||
this.editedData.notes = musicData?.notes || '';
|
||||
this.editedData.coverArt = musicData?.coverArt || '';
|
||||
break;
|
||||
case 'ART':
|
||||
const artData = suggestion.artData as any;
|
||||
this.editedData.artist = artData?.artist || '';
|
||||
this.editedData.description = artData?.description || '';
|
||||
this.editedData.imageUrl = artData?.imageUrl || '';
|
||||
break;
|
||||
case 'SHOW':
|
||||
const showData = suggestion.showData as any;
|
||||
this.editedData.type = showData?.type || 'TV_SERIES';
|
||||
this.editedData.notes = showData?.notes || '';
|
||||
this.editedData.coverImage = showData?.coverImage || '';
|
||||
break;
|
||||
case 'MANGA':
|
||||
const mangaData = suggestion.mangaData as any;
|
||||
this.editedData.author = mangaData?.author || '';
|
||||
this.editedData.notes = mangaData?.notes || '';
|
||||
this.editedData.coverImage = mangaData?.coverImage || '';
|
||||
break;
|
||||
}
|
||||
|
||||
this.showEditModal.set(true);
|
||||
}
|
||||
|
||||
openDeclineModal(suggestion: Suggestion) {
|
||||
@@ -660,6 +877,26 @@ export class AdminSuggestionsComponent implements OnInit {
|
||||
this.declineReason = '';
|
||||
}
|
||||
|
||||
closeEditModal() {
|
||||
this.showEditModal.set(false);
|
||||
this.editingSuggestion.set(null);
|
||||
this.editedData = {};
|
||||
}
|
||||
|
||||
async confirmAcceptWithEdits() {
|
||||
const suggestion = this.editingSuggestion();
|
||||
if (!suggestion) return;
|
||||
|
||||
try {
|
||||
await this.suggestionService.acceptSuggestionWithEdits(suggestion.id, this.editedData);
|
||||
alert(`"${this.editedData.title}" has been added to your collection with your edits!`);
|
||||
this.closeEditModal();
|
||||
this.loadSuggestions();
|
||||
} catch (error) {
|
||||
alert('Failed to accept suggestion. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
async confirmDecline() {
|
||||
const suggestion = this.decliningsuggestion();
|
||||
if (!suggestion) return;
|
||||
|
||||
Reference in New Issue
Block a user