Skip to content
Open
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}
8 changes: 4 additions & 4 deletions frontend/src/app/admin-navbar/admin-navbar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@
</ul>
<!-- Right section of navbar -->
<ul class="right-side">
<li id="navbar-fullscreen"><a href="#">Home</a></li>
<li id="navbar-fullscreen"><a href="#">Company</a></li>
<li id="navbar-fullscreen"><a href="#">Teams</a></li>
<li id="navbar-fullscreen"><a href="#">Users</a></li>
<li id="navbar-fullscreen"><a href="/home">Home</a></li>
<li id="navbar-fullscreen"><a href="/company">Company</a></li>
<li id="navbar-fullscreen"><a href="/teams">Teams</a></li>
<li id="navbar-fullscreen"><a href="/users">Users</a></li>
<li id="navbar-fullscreen"><a href="#">Logout</a></li>
<li (click)="showSidebar()" id="hamburger-menu">
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#1BA098">
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { UsersPageComponent } from './users-page/users-page.component';
import { ProjectsComponent } from './projects/projects.component';
import { CompanyComponent } from './company/company.component';
import { AnnouncementCardComponent } from './announcement-card/announcement-card.component';
import { TeamCardComponent } from './team-card/team-card.component';

@NgModule({
declarations: [
Expand All @@ -28,6 +29,7 @@ import { AnnouncementCardComponent } from './announcement-card/announcement-card
ProjectsComponent,
CompanyComponent,
AnnouncementCardComponent,
TeamCardComponent,
],
imports: [
BrowserModule,
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/app/homepage/homepage.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ <h1 class="text-lightPurple text-4xl font-extrabold">Announcements</h1>
class="fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 flex justify-center items-center hidden"
id="newAnnouncementForm"
>
<form class="bg-cardBackground p-6 rounded-lg shadow-lg w-96">
<form class="bg-cardBackground p-6 rounded-lg shadow-lg w-96" (ngSubmit)="submitAnnouncement()">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lightPurple text-lg font-semibold">Create Announcement</h2>
<button type="button" class="text-lightPurple text-xl" (click)="hideNewMenu()">✖</button>
Expand All @@ -35,11 +35,15 @@ <h2 class="text-lightPurple text-lg font-semibold">Create Announcement</h2>
<input
type="text"
id="title"
[(ngModel)]="newAnnouncement.title"
name="title"
class="w-full p-2 rounded border border-lightPurple mb-4 text-cardText bg-primary"
/>
<label for="message" class="block text-cardText mb-2">Message</label>
<textarea
id="message"
[(ngModel)]="newAnnouncement.message"
name="message"
class="w-full p-2 rounded border border-lightPurple mb-4 text-cardText bg-primary"
></textarea>
<button
Expand Down
77 changes: 62 additions & 15 deletions frontend/src/app/homepage/homepage.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,41 @@ import { AuthService } from '../services/auth.service'; // Adjust the path if ne
})
export class HomepageComponent implements OnInit {
announcements: any[] = []; // Announcements array initialized as empty
newAnnouncement = { title: '', message: '' }; // New announcement data
errorMessage: string | null = null; // To display error messages, if any
companyId: number | null = null; // Dynamically selected company ID

constructor(private authService: AuthService) {}

ngOnInit(): void {
const companyId = 2; // Replace with the actual company ID if dynamic
this.authService.getAnnouncements(companyId).subscribe({
next: (data) => {
// Transform API response if necessary
this.announcements = data.map((announcement: any) => ({
author: `${announcement.author.profile.firstName} ${announcement.author.profile.lastName}`,
date: new Date(announcement.date).toLocaleDateString(),
message: announcement.message,
}));
},
error: (err) => {
console.error('Failed to fetch announcements:', err);
this.errorMessage = 'Could not load announcements. Please try again later.';
},
});
// Retrieve the company ID from localStorage or AuthService
this.companyId = +this.authService.getCompanyId(); // Assuming getCompanyId returns a string that needs to be converted to number

if (this.companyId) {
this.loadAnnouncements();
} else {
console.error('No company selected');
this.errorMessage = 'Please select a company to view announcements.';
}
}

loadAnnouncements(): void {
if (this.companyId) {
this.authService.getAnnouncements(this.companyId).subscribe({
next: (data) => {
// Transform API response if necessary
this.announcements = data.map((announcement: any) => ({
author: `${announcement.author.profile.firstName} ${announcement.author.profile.lastName}`,
date: new Date(announcement.date).toLocaleDateString(),
message: announcement.message,
}));
},
error: (err) => {
console.error('Failed to fetch announcements:', err);
this.errorMessage = 'Could not load announcements. Please try again later.';
},
});
}
}

showNewMenu() {
Expand All @@ -39,4 +54,36 @@ export class HomepageComponent implements OnInit {
const form = document.getElementById('newAnnouncementForm');
if (form) form.style.display = 'none';
}

submitAnnouncement(): void {
if (!this.newAnnouncement.title || !this.newAnnouncement.message) {
alert('Please fill out both the title and message.');
return;
}

if (!this.companyId) {
alert('No company selected.');
return;
}

// Use AuthService to post the announcement to the correct company
this.authService.postAnnouncement(this.companyId, this.newAnnouncement.title, this.newAnnouncement.message)
.subscribe({
next: (response: any) => {
// Assuming response contains announcement details
this.announcements.unshift({
author: `${response.author.profile.firstName} ${response.author.profile.lastName}`,
date: new Date(response.date).toLocaleDateString(),
message: response.message,
});

this.hideNewMenu(); // Hide the form modal
this.newAnnouncement = { title: '', message: '' }; // Reset the form
},
error: (err) => {
console.error('Failed to create announcement:', err);
alert('Failed to create announcement. Please try again.');
},
});
}
}
8 changes: 3 additions & 5 deletions frontend/src/app/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,9 @@ export class AuthService {
return companyNames;
}

getTeams(): Object[] {
const user = this.getLoggedInUser();
console.log(user.teams)

return user.teams;
// Method to fetch teams for a specific company
getTeams(companyId: number): Observable<any[]> {
return this.http.get<any[]>(`${this.apiUrl}company/${companyId}/teams`);
}

// Sets the selected company
Expand Down
Empty file.
20 changes: 20 additions & 0 deletions frontend/src/app/team-card/team-card.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="bg-cardBackground text-cardText p-6 rounded-lg shadow-lg mt-6 max-w-xl mx-auto">
<div class="flex justify-between items-center mb-4">
<p class="font-bold text-lg">{{ team.name }}</p>
<p class="text-sm text-lightPurple">{{ team.projectsCount }} Projects</p>
</div>



<div *ngIf="team.teammates.length > 0">
<p class="text-sm text-lightPurple mb-2">Members:</p>
<div *ngFor="let member of team.teammates" class="text-base">
<p>{{ member.profile.firstName }} {{ member.profile.lastName }}</p>
</div>
</div>

<div *ngIf="team.teammates.length === 0" class="text-sm text-lightPurple mt-2">
No members assigned yet.
</div>
</div>

23 changes: 23 additions & 0 deletions frontend/src/app/team-card/team-card.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { TeamCardComponent } from './team-card.component';

describe('TeamCardComponent', () => {
let component: TeamCardComponent;
let fixture: ComponentFixture<TeamCardComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TeamCardComponent ]
})
.compileComponents();

fixture = TestBed.createComponent(TeamCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
10 changes: 10 additions & 0 deletions frontend/src/app/team-card/team-card.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'app-team-card',
templateUrl: './team-card.component.html',
styleUrls: ['./team-card.component.css'],
})
export class TeamCardComponent {
@Input() team: any; // Accept the team object as an input
}
29 changes: 24 additions & 5 deletions frontend/src/app/teams/teams.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
<div class="header"><h2>Teams</h2></div>
<!-- teams.component.ts -->
<div class="team-grid">
<app-team-view *ngFor="let teamId of teamIds" [teamId]="teamId"></app-team-view>
<!-- Conditional Navbar Rendering -->
<app-admin-navbar *ngIf="isAdmin()"></app-admin-navbar>
<!-- <app-worker-navbar *ngIf="!isAdmin()"></app-worker-navbar> -->

<!-- Main Container -->
<div class="flex flex-col items-center justify-start min-h-screen bg-primary mt-16 px-4">
<!-- Title Section -->
<div class="w-full flex justify-between items-center border-b border-lightPurple pb-6 mb-6 max-w-4xl">
<h1 class="text-lightPurple text-4xl font-extrabold">Teams</h1>
<button
class="bg-lightPurple hover:bg-purple text-white px-6 py-2 rounded-lg shadow-md"
(click)="showNewMenu()"
>
New Team
</button>
</div>


<!-- Error Message if no teams available -->
<div *ngIf="errorMessage" class="text-center text-red-500">{{ errorMessage }}</div>

<!-- Teams Cards Grid -->
<div *ngFor="let team of teams" class="w-full max-w-4xl mb-8">
<app-team-card [team]="team"></app-team-card>
</div>
</div>
85 changes: 81 additions & 4 deletions frontend/src/app/teams/teams.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,87 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../services/auth.service'; // Adjust the path if necessary

@Component({
selector: 'app-teams',
templateUrl: './teams.component.html',
styleUrls: ['./teams.component.css']
styleUrls: ['./teams.component.css'],
})
export class TeamsComponent {
teamIds: number[] = [1, 2,];
export class TeamsComponent implements OnInit {
teams: any[] = []; // To store fetched teams
errorMessage: string | null = null; // For error handling
companyId: number | null = null; // Company ID from AuthService or localStorage
newTeam = { name: '', description: '' }; // New team data
isNewTeamFormVisible = false; // To control the visibility of the new team form

constructor(private authService: AuthService) {}

ngOnInit(): void {
// Get the company ID from AuthService or localStorage
this.companyId = +this.authService.getCompanyId();

if (this.companyId) {
this.loadTeams();
} else {
this.errorMessage = 'No company selected';
}
}

// Load teams based on the selected company
loadTeams(): void {
if (this.companyId) {
this.authService.getTeams(this.companyId).subscribe({
next: (data) => {
this.teams = data; // Assign the teams to the component's teams array
},
error: (err) => {
console.error('Failed to fetch teams:', err);
this.errorMessage = 'Could not load teams. Please try again later.';
},
});
}
}

// Show the "New Team" form
showNewMenu(): void {
this.isNewTeamFormVisible = true;
}

// Hide the "New Team" form
hideNewMenu(): void {
this.isNewTeamFormVisible = false;
}

// Submit the new team form (optional)
submitNewTeam(): void {
if (!this.newTeam.name || !this.newTeam.description) {
alert('Please fill out both the name and description.');
return;
}

if (!this.companyId) {
alert('No company selected.');
return;
}

// Logic to create the new team (if needed)
// this.authService.createTeam(this.companyId, this.newTeam.name, this.newTeam.description)
// .subscribe({
// next: (response) => {
// console.log('New team created:', response);
// this.teams.unshift(response); // Add the new team to the list
// this.hideNewMenu(); // Hide the form modal
// this.newTeam = { name: '', description: '' }; // Reset the form
// },
// error: (err) => {
// console.error('Failed to create team:', err);
// alert('Failed to create team. Please try again.');
// },
// });
}

// Determine if the logged-in user is an admin
isAdmin(): boolean {
return this.authService.isAdmin();
}
}

4 changes: 2 additions & 2 deletions frontend/src/app/worker-navbar/worker-navbar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
</ul>
<!-- Right section of navbar -->
<ul class="right-side">
<li id="navbar-fullscreen"><a href="#">Home</a></li>
<li id="navbar-fullscreen"><a href="#">Teams</a></li>
<li id="navbar-fullscreen"><a href="/home">Home</a></li>
<li id="navbar-fullscreen"><a href="/teams">Teams</a></li>
<li id="navbar-fullscreen"><a href="#">Logout</a></li>
<li onclick=showSidebar() id="hamburger-menu">
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#1BA098">
Expand Down