import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AngularEditorConfig } from '@josipv/angular-editor-k2'; import { AuthenticationService } from 'src/app/service/authentication.service'; import { BlogService } from 'src/app/service/blog.service'; import { ProfessorService } from 'src/app/service/professor.service'; @Component({ selector: 'app-blog', templateUrl: './blog.component.html', styleUrls: ['./blog.component.css'], }) export class BlogComponent implements OnInit { blogs: any[] = []; allProfessors: any[] = []; selectedBlog: any = null; blogForm: FormGroup; editing: boolean = false; loggedInUser: any; currentBlog: any = null; isShowForm = false; content = ''; // Image upload properties selectedImage: File | null = null; imagePreviewUrl: string | null = null; uploadingImage: boolean = false; constructor( private blogService: BlogService, private authService: AuthenticationService, private professorService: ProfessorService, private fb: FormBuilder ) { // Initialize form with form controls this.blogForm = this.fb.group({ title: ['', Validators.required], content: ['', Validators.required], professors: [[], Validators.required], tags: ['', Validators.required], posted: [true], }); } editorConfig: AngularEditorConfig = { editable: true, spellcheck: true, height: '10', minHeight: '0', maxHeight: 'auto', width: 'auto', minWidth: '0', translate: 'yes', enableToolbar: true, showToolbar: true, placeholder: 'Enter text here...', defaultParagraphSeparator: '', defaultFontName: '', defaultFontSize: '', fonts: [ { class: 'arial', name: 'Arial' }, { class: 'times-new-roman', name: 'Times New Roman' }, { class: 'calibri', name: 'Calibri' }, { class: 'comic-sans-ms', name: 'Comic Sans MS' }, ], customClasses: [ { name: 'quote', class: 'quote', }, { name: 'redText', class: 'redText', }, { name: 'titleText', class: 'titleText', tag: 'h1', }, ], sanitize: true, toolbarPosition: 'top', toolbarHiddenButtons: [['bold', 'italic'], ['fontSize']], }; ngOnInit(): void { this.loggedInUser = this.authService.getUserFromLocalStorage(); this.professorService .getAllProfessors() .subscribe((res) => (this.allProfessors = res.content)); this.loadBlogs(); // Subscribe to form value changes to update content for preview this.blogForm.get('content')?.valueChanges.subscribe((value) => { this.content = value; }); } showForm() { this.isShowForm = true; this.resetForm(); } showTable() { this.isShowForm = false; this.resetForm(); } loadBlogs() { this.blogService.getBlogs().subscribe(data => { this.blogs = data; }); } createBlog() { this.showForm(); this.blogForm.reset(); this.selectedBlog = null; this.editing = false; } editBlog(blog: any) { this.selectedBlog = blog; this.blogForm.patchValue({ title: blog.title, content: blog.content, posted: blog.posted, professors: blog.professors.map((prof: any) => prof.id), tags: blog.tags.join(', ') }); // Set image preview if exists if (blog.imageUrl) { this.imagePreviewUrl = blog.imageUrl; } this.editing = true; this.isShowForm = true; } // Image upload methods onImageSelected(event: any) { const file = event.target.files[0]; if (file) { // Validate file type if (!file.type.startsWith('image/')) { alert('Please select a valid image file.'); return; } // Validate file size (10MB max) const maxSize = 10 * 1024 * 1024; // 10MB in bytes if (file.size > maxSize) { alert('File size must be less than 10MB.'); return; } this.selectedImage = file; // Create preview URL const reader = new FileReader(); reader.onload = (e: any) => { this.imagePreviewUrl = e.target.result; }; reader.readAsDataURL(file); } } removeImage() { this.selectedImage = null; this.imagePreviewUrl = null; // Clear the file input const fileInput = document.getElementById('image') as HTMLInputElement; if (fileInput) { fileInput.value = ''; } } async uploadImage(): Promise { if (!this.selectedImage) return null; this.uploadingImage = true; try { const response = await this.blogService.uploadImage(this.selectedImage).toPromise(); return response.url; } catch (error) { console.error('Error uploading image:', error); alert('Failed to upload image. Please try again.'); return null; } finally { this.uploadingImage = false; } } async saveBlog() { if (this.blogForm.valid) { let imageUrl = null; // Upload image if selected if (this.selectedImage) { imageUrl = await this.uploadImage(); if (!imageUrl) { return; // Stop if image upload failed } } const blogData = this.blogForm.value; // Convert tags to array and professors to array of IDs blogData.tags = blogData.tags.split(',').map((tag: string) => tag.trim()); blogData.professors = blogData.professors || []; // Add image URL if uploaded, or keep existing image for updates if (imageUrl) { blogData.imageUrl = imageUrl; } else if (this.editing && this.selectedBlog && this.selectedBlog.imageUrl && this.imagePreviewUrl) { // Keep existing image URL if editing and no new image selected blogData.imageUrl = this.selectedBlog.imageUrl; } blogData.author = this.loggedInUser._id; if (this.editing && this.selectedBlog) { this.blogService.updateBlog(this.selectedBlog.id, blogData).subscribe({ next: () => { this.loadBlogs(); this.resetForm(); this.isShowForm = false; alert('Blog updated successfully!'); }, error: (error) => { console.error('Error updating blog:', error); alert('Failed to update blog. Please try again.'); } }); } else { this.blogService.createBlog(blogData).subscribe({ next: () => { this.loadBlogs(); this.resetForm(); this.isShowForm = false; alert('Blog created successfully!'); }, error: (error) => { console.error('Error creating blog:', error); alert('Failed to create blog. Please try again.'); } }); } } else { // Mark all fields as touched to show validation errors Object.keys(this.blogForm.controls).forEach(key => { this.blogForm.get(key)?.markAsTouched(); }); alert('Please fill in all required fields.'); } } deleteBlog(blog: any) { if (confirm('Are you sure you want to delete this blog?')) { this.blogService.deleteBlog(blog.id).subscribe({ next: () => { this.loadBlogs(); alert('Blog deleted successfully!'); }, error: (error) => { console.error('Error deleting blog:', error); alert('Failed to delete blog. Please try again.'); } }); } } resetForm() { this.blogForm.reset(); this.selectedBlog = null; this.editing = false; this.selectedImage = null; this.imagePreviewUrl = null; this.blogForm.patchValue({ professors: [], tags: '', posted: true }); // Clear the file input const fileInput = document.getElementById('image') as HTMLInputElement; if (fileInput) { fileInput.value = ''; } } // Utility method to check if form field has error hasError(fieldName: string): boolean { const field = this.blogForm.get(fieldName); return !!(field && field.invalid && field.touched); } // Utility method to get error message for a field getErrorMessage(fieldName: string): string { const field = this.blogForm.get(fieldName); if (field && field.errors && field.touched) { if (field.errors['required']) { return `${fieldName} is required.`; } } return ''; } }