Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions apps/fakeoverflow-angular/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Routes } from '@angular/router';
import { authGuard } from '@guards/auth-guard';

export const routes: Routes = [
{
path: 'auth',
Expand Down Expand Up @@ -28,22 +27,26 @@ export const routes: Routes = [
]
},
{ path: 'home', loadComponent: () => import('./pages/home/home/home').then(m => m.Home), },
{
{
path: 'post',
children: [
{
path: 'create',
loadComponent: () => import('./pages/home/home/create-post/post').then(m => m.PostComponent),
canActivate: [authGuard],
title: 'Create Post | FakeOverflow'
},
{
path: ":id",
loadComponent: () => import('./pages/home/home/details/details').then(m => m.DetailsComponent),
title: 'Post | FakeOverflow'
}
]
]
},
{ path: 'update', loadComponent: () => import('./pages/home/home/UpdatePost/update').then(m => m.UpdateComponent) },
{ path: 'detail', loadComponent: () => import('./pages/home/home/PostDetails/details').then(m => m.DetailsComponent) },
{ path: 'detail', loadComponent: () => import('@pages/home/home/details/details').then(m => m.DetailsComponent) },
{ path: 'personalhome', loadComponent: () => import('./pages/home/home/PersonalQuestionsHome/personalHome').then(m => m.PersonalHome) },

{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: '**', redirectTo: 'home' }

{ path: '**', redirectTo: 'home' },
];

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ <h1 class="text-3xl font-bold text-gray-900 mb-6">Ask question</h1>
<form [formGroup]="formGroup" (ngSubmit)="submit()" novalidate class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Title</label>
<input formControlName="title" name="title" class="w-full px-4 py-2.5 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Be specific">
<input formControlName="title" name="title" class="w-full px-4 py-2.5 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Please enter your title">
<div class="mt-1 text-sm text-red-600" *ngIf="formGroup.controls['title']?.touched && formGroup.controls['title']?.invalid">Enter at least 10 characters</div>
</div>

<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Body</label>
<textarea name="body" formControlName="content" rows="8" class="w-full px-4 py-2.5 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Describe your question"></textarea>
<textarea name="body" formControlName="content" rows="8" class="w-full px-4 py-2.5 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Describle the post in detail"></textarea>
<div class="mt-1 text-sm text-red-600" *ngIf="formGroup.controls['title']?.touched && formGroup.controls['title']?.invalid">Enter at least 20 characters</div>
</div>
<div class="flex items-center justify-between">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<app-navbar></app-navbar>

<div class="min-h-screen bg-gray-50">
<div class="max-w-[100rem] mx-auto flex flex-col lg:flex-row gap-8 px-6 lg:px-10 py-10">

<div class="flex-1 space-y-6">
<div *ngIf="!loading && post" class="flex flex-col gap-2">
<app-post-title [post]="post"></app-post-title>
<app-post-question class="mb-5" [post]="post"></app-post-question>
<app-post-answer [post]="post"></app-post-answer>
</div>
</div>

<aside class="hidden lg:block w-[300px] shrink-0">
<div class="bg-white border border-gray-200 rounded-2xl shadow-sm p-5">
<h2 class="text-lg font-semibold text-gray-800 mb-3 border-b border-gray-100 pb-2">
Related Posts
</h2>
<ul class="space-y-3 text-sm">
<li><a href="#" class="text-blue-600 hover:text-blue-700 hover:underline">What are interest rate cuts?</a></li>
<li><a href="#" class="text-blue-600 hover:text-blue-700 hover:underline">Impact of Fed decisions on markets</a></li>
<li><a href="#" class="text-blue-600 hover:text-blue-700 hover:underline">AI in financial news detection</a></li>
</ul>
</div>
</aside>

</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Component, OnInit , inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, NgForm } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import {Navbar} from '@shared/navbar/navbar';
import { PostService } from '../../../../../../../../packages/fakeoverflow-angular-services/api/post.service';
import {PostTitle} from '@pages/home/home/details/post-title/post-title';
import {PostQuestion} from '@pages/home/home/details/post-question/post-question';
import {PostAnswer} from '@pages/home/home/details/post-answer/post-answer';
import {FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse} from 'fakeoverflow-angular-services';
import {HotToastService} from '@ngxpert/hot-toast';
import {Spinner} from '@services/spinner';

@Component({
selector: 'app-post',
standalone: true,
imports: [Navbar, CommonModule, FormsModule, PostTitle, PostQuestion, PostAnswer],
templateUrl: './details.html',
styleUrl: './details.scss'
})
export class DetailsComponent implements OnInit {
private readonly postService = inject(PostService);
private readonly route = inject(ActivatedRoute);
protected readonly spinnerService = inject(Spinner);

protected post: FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse | null = null;
loading = false;
errorMessage = '';
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
if (!id) {
this.errorMessage = 'No post ID provided.';
return;
}
this.loading = true;

const pageSpinner = this.spinnerService.for("Loading post");
this.postService.getPostById(id).subscribe({
next: (response) => {
pageSpinner.release()
this.post = response;
this.loading = false;
},
error: (err) => {
console.error('Error loading post:', err);
this.errorMessage = 'Failed to load post.';
this.loading = false;
pageSpinner.release()
}
});

}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<h2 class="text-2xl font-semibold text-gray-900 mb-4">Answers</h2>

<div *ngIf="loading" class="text-gray-600 py-4">Loading answers...</div>
<div *ngIf="errorMessage" class="text-red-600 py-4">{{ errorMessage }}</div>

<!-- List of answers -->
<div *ngIf="!loading && answers?.length > 0" class="space-y-6">
<div
*ngFor="let answer of answers"
class="border border-gray-200 rounded-lg shadow-sm p-4"
>
<div class="flex items-start space-x-4">
<!-- Voting -->
<div class="flex flex-col items-center text-gray-500">
<button pButton icon="pi pi-chevron-up" class="p-button-text"></button>
<span class="text-sm font-medium">0</span>
<button pButton icon="pi pi-chevron-down" class="p-button-text"></button>
</div>

<!-- Answer Body -->
<div class="flex-1">
<p class="text-gray-800 whitespace-pre-line leading-relaxed mb-3">
{{ answer.content }}
</p>

<div class="flex items-center text-sm text-gray-500">
<img
*ngIf="answer.createdOn?.user?.profilePicture"
[src]="answer.createdOn.user.profilePicture"
alt="Profile"
class="w-6 h-6 rounded-full"
/>
<span class="ml-2">{{ answer.createdOn?.user?.name }}</span>
<span class="ml-1">· {{ answer.createdOn?.activityOn | date: 'medium' }}</span>
</div>
</div>
</div>
</div>
</div>

<!-- No answers -->
<div *ngIf="!loading && (!answers || answers.length === 0)" class="text-gray-500 py-4">
No answers yet. Be the first to respond!
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Component, input, signal} from '@angular/core';
import {FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse} from 'fakeoverflow-angular-services';
import {ButtonDirective} from 'primeng/button';
import {DatePipe} from '@angular/common';

@Component({
selector: 'app-post-answer',
imports: [
ButtonDirective,
DatePipe
],
templateUrl: './post-answer.html',
styleUrl: './post-answer.scss'
})
export class PostAnswer {
public post = input.required<FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse>();
protected readonly errorMessage = signal<string | null>(null);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-start space-x-4">
<!-- Voting -->
<div class="flex flex-col items-center text-gray-500">
<button pButton icon="pi pi-chevron-up" class="p-button-text"></button>
<span class="text-sm font-medium">{{ post().votes }}</span>
<button pButton icon="pi pi-chevron-down" class="p-button-text"></button>
</div>

<!-- Question Content -->
<div class="flex-1">
<p class="text-gray-800 whitespace-pre-line leading-relaxed mb-4">
{{ post().content }}
</p>

<!-- Tags -->
<div class="flex flex-wrap gap-2">
<span
*ngFor="let tag of post().tags"
class="bg-blue-50 text-blue-700 text-sm px-3 py-1 rounded-full border border-blue-200"
>
{{ tag }}
</span>
</div>

<!-- Updated Info -->
<div class="mt-4 text-xs text-gray-500">
Last updated on {{ post().updatedOn?.activityOn | date: 'medium' }}
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Component, input} from '@angular/core';
import {FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse} from 'fakeoverflow-angular-services';
import {ButtonDirective} from 'primeng/button';
import {DatePipe} from '@angular/common';

@Component({
selector: 'app-post-question',
imports: [
ButtonDirective,
DatePipe
],
templateUrl: './post-question.html',
styleUrl: './post-question.scss'
})
export class PostQuestion {
public post = input.required<FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-start justify-between">
<div class="flex-1">
<h2 class="text-2xl font-semibold text-gray-900 leading-snug mb-2">
{{ post().title }}
</h2>

<div class="flex items-center space-x-2 text-sm text-gray-500">
<img
*ngIf="post().createdOn?.user?.profilePicture"
[src]="post().createdOn!.user!.profilePicture"
alt="Profile"
class="w-6 h-6 rounded-full"
/>
<span>Asked by</span>
<span class="font-medium text-gray-800">{{ post().createdOn?.user?.name }}</span>
<span>· {{ post().createdOn?.activityOn | date: 'medium' }}</span>
</div>
</div>

<div class="text-sm text-gray-500">
<div>{{ post().views }} views</div>
<div>{{ post().votes }} votes</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Component, input} from '@angular/core';
import {FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse} from 'fakeoverflow-angular-services';
import {DatePipe} from '@angular/common';

@Component({
selector: 'app-post-title',
imports: [
DatePipe
],
templateUrl: './post-title.html',
styleUrl: './post-title.scss'
})
export class PostTitle {

public post = input.required<FakeoverFlowBackendHttpApiFeaturesPostsViewPostViewPostResponse>();


}