Skip to content

Commit

Permalink
Merge pull request #360 from COS301-SE-2024/feature/darkTheme
Browse files Browse the repository at this point in the history
Improved the dark theme
  • Loading branch information
TebogoYungMercykay authored Sep 27, 2024
2 parents 83a3594 + 6da7a96 commit 18b9549
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 61 deletions.
10 changes: 5 additions & 5 deletions backend/src/modules/issues/repositories/issueRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export default class IssueRepository {
const days =
forecastData && !forecastError ? formatTime(forecastData) : "6 days";
const information = !issue.resolved_at
? `This issue may take at least ${days} to be resolved. Please check back if your issue is not resolved by then.`
? `This issue may take around ${days} to be resolved based on similar issues in this area.`
: "This issue has already been resolved.";

return {
Expand Down Expand Up @@ -249,7 +249,7 @@ export default class IssueRepository {
const days =
forecastData && !forecastError ? formatTime(forecastData) : "6 days";
const information = !data.resolved_at
? `This issue may take at least ${days} to be resolved. Please check back if your issue is not resolved by then.`
? `This issue may take around ${days} to be resolved based on similar issues in this area.`
: "This issue has already been resolved.";

return {
Expand Down Expand Up @@ -427,7 +427,7 @@ export default class IssueRepository {
const days =
forecastData && !forecastError ? formatTime(forecastData) : "6 days";
const information = !issue.resolved_at
? `This issue may take at least ${days} to be resolved. Please check back if your issue is not resolved by then.`
? `This issue may take around ${days} to be resolved based on similar issues in this area.`
: "This issue has already been resolved.";

return {
Expand Down Expand Up @@ -677,7 +677,7 @@ export default class IssueRepository {
const days =
forecastData && !forecastError ? formatTime(forecastData) : "6 days";
const information = !issue.resolved_at
? `This issue may take at least ${days} to be resolved. Please check back if your issue is not resolved by then.`
? `This issue may take around ${days} to be resolved based on similar issues in this area.`
: "This issue has already been resolved.";

return {
Expand Down Expand Up @@ -772,7 +772,7 @@ export default class IssueRepository {
const days =
forecastData && !forecastError ? formatTime(forecastData) : "6 days";
const information = !issue.resolved_at
? `This issue may take at least ${days} to be resolved. Please check back if your issue is not resolved by then.`
? `This issue may take around ${days} to be resolved based on similar issues in this area.`
: "This issue has already been resolved.";

return {
Expand Down
4 changes: 2 additions & 2 deletions frontend/__tests__/pages/home/Analytics.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jest.mock('@/components/ReportCharts/Reports', () => () => <div>Reports Componen
describe('Tabs Component', () => {
test('renders Reports tab by default', () => {
render(<Tabs />);
expect(screen.getByText('Reports')).toBeInTheDocument();
expect(screen.getByText('Statistics')).toBeInTheDocument();
expect(screen.getByText('Reports Component')).toBeInTheDocument();
});

Expand All @@ -20,7 +20,7 @@ describe('Tabs Component', () => {

test('highlights the active tab correctly', () => {
render(<Tabs />);
const reportsTab = screen.getByText('Reports');
const reportsTab = screen.getByText('Statistics');
const visualizationsTab = screen.getByText('Visualizations');

fireEvent.click(reportsTab);
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(home)/analytics/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Tabs() {
onClick={() => handleTabClick('Reports')}
aria-current={activeTab === 'Reports' ? 'page' : undefined}
>
Reports
Statistics
</button>
</li>
<li className="flex-1">
Expand Down
21 changes: 17 additions & 4 deletions frontend/components/Issue/Issue.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect } from "react";
import { useTheme } from 'next-themes';
import {
Card,
CardContent,
Expand Down Expand Up @@ -38,6 +39,7 @@ const Issue: React.FC<IssueProps> = ({
}) => {
const { user } = useUser();
const router = useRouter();
const { theme } = useTheme();
const [type, setType] = useState("");
const queryClient = useQueryClient();
const [showSubscribeDropdown, setShowSubscribeDropdown] = useState(false);
Expand Down Expand Up @@ -285,6 +287,10 @@ const Issue: React.FC<IssueProps> = ({
return text.replace(/@(\w+)/g, '<span class="text-primary font-semibold">@$1</span>');
};

const dropdownClasses = `origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg ring-1 ring-opacity-5 focus:outline-none ${
theme === "dark" ? "bg-[#262626] text-white ring-gray-700" : "bg-white text-gray-700 ring-black"
}`;

return (
<>
<Card className="mb-4" id={id} data-testid="issue-item">
Expand Down Expand Up @@ -341,29 +347,35 @@ const Issue: React.FC<IssueProps> = ({
{showSubscribeDropdown && (
<div
ref={dropdownRef}
className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none"
className={dropdownClasses}
role="menu"
aria-orientation="vertical"
aria-labelledby="subscribe-menu"
>
<div className="py-1" role="none">
<button
onClick={() => handleSubscribe("Issue")}
className="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900 w-full text-left"
className={`block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900 w-full text-left ${
theme === "dark" ? "hover:bg-[#0C0A09] hover:text-white" : ""
}`}
role="menuitem"
>
Subscribe to Issue
</button>
<button
onClick={() => handleSubscribe("Category")}
className="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900 w-full text-left"
className={`block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900 w-full text-left ${
theme === "dark" ? "hover:bg-[#0C0A09] hover:text-white" : ""
}`}
role="menuitem"
>
Subscribe to Category
</button>
<button
onClick={() => handleSubscribe("Location")}
className="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900 w-full text-left"
className={`block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900 w-full text-left ${
theme === "dark" ? "hover:bg-[#0C0A09] hover:text-white" : ""
}`}
role="menuitem"
>
Subscribe to Location
Expand All @@ -379,6 +391,7 @@ const Issue: React.FC<IssueProps> = ({
isOwner={isOwner}
onAction={handleMenuAction}
onSubscribe={handleSubscribe}

/>
)}
{isLoading && <Loader2 className="h-6 w-6 animate-spin text-green-400" />}
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/MoreMenu/MoreMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const MoreMenu: React.FC<MoreMenuProps> = ({
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
className="flex items-center rounded-full p-1 hover:bg-gray-200"
className="flex items-center rounded-full p-1 "
title="More Options"
>
<MoreHorizontal />
Expand Down
9 changes: 8 additions & 1 deletion frontend/components/Notifications/NotificationsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { subscribe } from "@/lib/api/subscription";
import { useQuery } from "@tanstack/react-query";
import { useUser } from "@/lib/contexts/UserContext";
import ErrorDisplay from '@/components/ui/error_display';
import { useTheme } from "next-themes";

import type { NotificationType } from "@/lib/types";
import { formatLongDate } from "@/lib/utils";
Expand Down Expand Up @@ -77,6 +78,8 @@ const NotificationsList: React.FC = () => {
);
}

const { theme } = useTheme();

const addSuspendMessage = (notif: NotificationType) =>
notif.content.includes("external resolution rejected")
? notif.content + " You will be suspended from resolving until " + formatLongDate(
Expand All @@ -92,7 +95,11 @@ const NotificationsList: React.FC = () => {

<li
key={index}
className="flex items-start space-x-3 p-4 hover:bg-gray-50"
className={`flex items-start space-x-3 p-4 transition duration-200
${theme === "dark"
? "hover:bg-[#262626] hover:text-white"
: "hover:bg-gray-300 hover:text-black"}
`}
>
<Link
href={getNotificationLink(notification.type, (notification.type != "points") ? notification.issue_id : "none")}
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/OrganizationTabs/InformationTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { checkUserMembership } from '@/lib/api/checkUserMembership';
import { requestReport } from '@/lib/api/requestReport';
import { useUser } from '@/lib/contexts/UserContext';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { PenSquare, Star, BarChart, Sparkles } from 'lucide-react';
import { PenSquare, Star, BarChart, PieChart } from 'lucide-react';
import OrgPost from '@/components/OrgPost/OrgPost';
import CreateOrgPost from '@/components/CreatePost/CreatePost';
import { useToast } from '../ui/use-toast';
Expand Down Expand Up @@ -185,7 +185,7 @@ export default function InformationTab({
<Dialog open={showReportModal} onOpenChange={setShowReportModal}>
<DialogTrigger asChild>
<Button className="w-full">
<Sparkles className="w-4 h-4 mr-2" />
<PieChart className="w-4 h-4 mr-2" />
Get Your Detailed Report
</Button>
</DialogTrigger>
Expand Down
114 changes: 70 additions & 44 deletions frontend/components/ResolutionModal/ResolutionModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,32 @@ interface OrganizationToggleProps {
onToggle: (id: string) => void;
}

const OrganizationToggle: React.FC<OrganizationToggleProps> = ({ organization, isSelected, onToggle }) => (
<Toggle
pressed={isSelected}
onPressedChange={() => onToggle(organization.id)}
className={cn(
"flex flex-col items-center justify-center p-2 rounded-md",
"w-24 h-24 border-2",
isSelected ? "border-primary bg-primary/10" : "border-gray-200 hover:bg-gray-100",
"transition-all duration-200 ease-in-out"
)}
>
<Avatar className="w-12 h-12 mb-2">
<AvatarImage src={organization.profile_photo} alt={organization.name} />
<AvatarFallback>{organization.name.charAt(0)}</AvatarFallback>
</Avatar>
<span className="text-xs text-center line-clamp-2">{organization.name}</span>
</Toggle>
);
const OrganizationToggle: React.FC<OrganizationToggleProps> = ({ organization, isSelected, onToggle }) => {
const { theme } = useTheme();

return (
<Toggle
pressed={isSelected}
onPressedChange={() => onToggle(organization.id)}
className={cn(
"flex flex-col items-center justify-center p-2 rounded-md",
"w-24 h-24 border-2",
isSelected ? "border-primary bg-primary/10" : "border-gray-200",
theme === 'dark'
? "hover:bg-[#0C0A09] hover:text-white"
: "hover:bg-gray-100",
"transition-all duration-200 ease-in-out"
)}
>
<Avatar className="w-12 h-12 mb-2">
<AvatarImage src={organization.profile_photo} alt={organization.name} />
<AvatarFallback>{organization.name.charAt(0)}</AvatarFallback>
</Avatar>
<span className="text-xs text-center line-clamp-2">{organization.name}</span>
</Toggle>
);
};


const ResolutionModal: React.FC<ResolutionModalProps> = ({
isOpen,
Expand Down Expand Up @@ -264,31 +272,47 @@ const ResolutionModal: React.FC<ResolutionModalProps> = ({
</div>
</div>
{isSearchOpen && searchResults.length > 0 && (
<div className="absolute z-10 w-full mt-1 bg-white border border-gray-200 rounded-md shadow-lg max-h-60 overflow-auto">
{searchResults.map((item) => (
<div
key={item.id}
className="px-4 py-2 hover:bg-gray-100 cursor-pointer"
onClick={() => {
setResolvedBy(item.name);
setResolverID(item.id);
setSearchQuery(item.name);
setIsSearchOpen(false);
}}
>
<span className="font-medium text-foreground">
{item.name}
</span>
<span className="ml-2 text-sm text-muted-foreground">
@{item.username}
</span>
<span className="px-2 bg-gray-200 rounded absolute right-2">
{item.type}
</span>
</div>
))}
</div>
)}
<div className={cn(
"absolute z-10 w-full mt-1 border rounded-md shadow-lg max-h-60 overflow-auto",
theme === "dark"
? "bg-[#262626] border-gray-700"
: "bg-white border-gray-200"
)}>
{searchResults.map((item) => (
<div
key={item.id}
className={cn(
"px-4 py-2 cursor-pointer",
theme === "dark"
? "hover:bg-[#404040] text-white"
: "hover:bg-gray-100 text-foreground"
)}
onClick={() => {
setResolvedBy(item.name);
setResolverID(item.id);
setSearchQuery(item.name);
setIsSearchOpen(false);
}}
>
<span className="font-medium">
{item.name}
</span>
<span className={cn(
"ml-2 text-sm",
theme === "dark" ? "text-gray-400" : "text-muted-foreground"
)}>
@{item.username}
</span>
<span className={cn(
"px-2 rounded absolute right-2",
theme === "dark" ? "bg-gray-700" : "bg-gray-200"
)}>
{item.type}
</span>
</div>
))}
</div>
)}
</div>
)}

Expand Down Expand Up @@ -343,10 +367,12 @@ const ResolutionModal: React.FC<ResolutionModalProps> = ({
className={cn(
"px-4 py-2 rounded-lg",
theme === "dark"
? "bg-gray-700 text-white hover:bg-gray-600"
? "bg-[#0C0A09] text-white hover:bg-[#262626]"
: "bg-gray-200 text-gray-800 hover:bg-gray-300"
)}
>


<Upload className="w-4 h-4 mr-2" />
Upload Image
</Button>
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/ui/resolution-popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default function InfoPopover({ message }: PopoverProps) {
<h3 className="font-semibold text-gray-900 dark:text-gray-200">Resolution Information</h3>
</div>
<div className="px-3 py-2">
<p>{message ?? 'This issue may take at least 6 day(s) to be resolved. Please check back if your issue is not resolved by then.'}</p>
<p>{message ?? 'This issue may take around 6 day(s) to be resolved based on similar issues in this area.'}</p>
</div>
{/* <div className="absolute w-3 h-3 bg-white transform rotate-45 border-l border-t border-gray-200 dark:bg-gray-900 dark:border-gray-800"></div> */}
</div>
Expand Down

0 comments on commit 18b9549

Please sign in to comment.