From 329b234b2f3e18b36493f1e4b495f1abdb49769a Mon Sep 17 00:00:00 2001 From: s223456323 Date: Sun, 15 Sep 2024 00:02:19 +1000 Subject: [PATCH 1/2] update the usecase and usecases files and test case --- next_webapp/src/mongodb/UseCase.js | 18 +++---- next_webapp/src/mongodb/UseCases.js | 56 ++++++++++++++++++---- next_webapp/src/mongodb/test-stats.js | 68 ++++++++++++++++++++------- 3 files changed, 107 insertions(+), 35 deletions(-) diff --git a/next_webapp/src/mongodb/UseCase.js b/next_webapp/src/mongodb/UseCase.js index 3a1cf564a..043a32c54 100644 --- a/next_webapp/src/mongodb/UseCase.js +++ b/next_webapp/src/mongodb/UseCase.js @@ -1,4 +1,3 @@ -// models/UseCase.js const mongoose = require('mongoose'); const UseCaseSchema = new mongoose.Schema({ @@ -7,16 +6,19 @@ const UseCaseSchema = new mongoose.Schema({ required: [true, 'Please provide a tag for this use case.'], maxlength: [30, 'Tag cannot be more than 30 characters'], }, + publishNumber: { + type: String, + required: [true, 'Please provide a publish number for this use case.'], + }, popularity: { - type: Number, - required: true, - min: [0, 'Popularity must be a non-negative number'], - max: [100, 'Popularity cannot be more than 100'], + type: String, + required: [true, 'Please provide a popularity percentage for this use case.'], + match: [/^\d{1,3}%$/, 'Popularity must be a percentage in the format XX%'] }, - semester: { + trimester: { type: String, - required: [true, 'Please provide a semester for this use case.'], - match: [/^\d{4}-T[1-3]$/, 'Semester must be in the format YYYY-T1, YYYY-T2, or YYYY-T3'] + required: [true, 'Please provide a trimester for this use case.'], + match: [/^[1-3]$/, 'Trimester must be one of "1", "2", or "3"'] }, }); diff --git a/next_webapp/src/mongodb/UseCases.js b/next_webapp/src/mongodb/UseCases.js index b8db24e1c..29aa9a67b 100644 --- a/next_webapp/src/mongodb/UseCases.js +++ b/next_webapp/src/mongodb/UseCases.js @@ -4,30 +4,51 @@ const UseCase = require('./UseCase'); async function handleRequest(req, res) { await dbConnect(); - const { method } = req; + const { method, query } = req; + const { tag, trimester, stats } = query; switch (method) { case 'GET': - if (req.query.stats === 'true') { + if (stats === 'true') { console.log('Called Stats method'); - // Handle statistics request + // Prepare filter criteria + const filter = {}; + if (tag) filter.tag = tag; + if (trimester) filter.trimester = trimester; + try { const stats = await UseCase.aggregate([ + { + $match: filter // Apply filters based on tag and trimester + }, { $group: { _id: { tag: "$tag", - semester: "$semester" + trimester: "$trimester" }, - averagePopularity: { $avg: "$popularity" }, - count: { $sum: 1 } + totalPublishNumber: { $sum: { $toInt: "$publishNumber" } }, // Sum of publish numbers + averagePopularity: { + $avg: { + $toDouble: { + $substr: ["$popularity", 0, { + $subtract: [ + { $strLenCP: "$popularity" }, + 1 + ] + }] + } + } + }, // Average popularity + count: { $sum: 1 } // Count of use cases } }, { $project: { _id: 0, tag: "$_id.tag", - semester: "$_id.semester", + trimester: "$_id.trimester", + totalPublishNumber: 1, averagePopularity: { $round: ["$averagePopularity", 2] }, // Optional: round to 2 decimal places count: 1 } @@ -38,10 +59,25 @@ async function handleRequest(req, res) { res.status(400).json({ success: false, error: error.message }); } } else { - // Handle normal GET request + console.log('Called Use Case Count by Trimester'); + // Handle count by trimester request try { - const useCases = await UseCase.find({}); - res.status(200).json({ success: true, data: useCases }); + const trimesterCounts = await UseCase.aggregate([ + { + $group: { + _id: "$trimester", // Group by trimester + count: { $sum: 1 } // Count the number of use cases in each trimester + } + }, + { + $project: { + _id: 0, + trimester: "$_id", + count: 1 + } + } + ]); + res.status(200).json({ success: true, data: trimesterCounts }); } catch (error) { res.status(400).json({ success: false, error: error.message }); } diff --git a/next_webapp/src/mongodb/test-stats.js b/next_webapp/src/mongodb/test-stats.js index d1d425eaa..6ed996cd6 100644 --- a/next_webapp/src/mongodb/test-stats.js +++ b/next_webapp/src/mongodb/test-stats.js @@ -1,36 +1,42 @@ const dbConnect = require('../../lib/mongodb'); const handleRequest = require('./UseCases'); const UseCase = require('./UseCase'); + async function main() { await dbConnect(); console.log('Inserting dummy data...'); await UseCase.deleteMany({}); // Clear existing data - const dummyData = [ - { tag: 'Frontend', semester: '2024-T1', popularity: 75 }, - { tag: 'Backend', semester: '2024-T2', popularity: 60 }, - { tag: 'Frontend', semester: '2024-T3', popularity: 80 }, - { tag: 'Frontend', semester: '2024-T1', popularity: 55 }, - { tag: 'Backend', semester: '2024-T3', popularity: 70 } + // Dummy data provided + const caseStudies = [ + { tag: "Safety and Well-being", publishNumber: "4", popularity: "11%", trimester: "1" }, + { tag: "Environment and Sustainability", publishNumber: "5", popularity: "40%", trimester: "2" }, + { tag: "Business and activity", publishNumber: "8", popularity: "90%", trimester: "3" }, + { tag: "Safety and Well-being", publishNumber: "4", popularity: "11%", trimester: "2" }, + { tag: "Environment and Sustainability", publishNumber: "5", popularity: "90%", trimester: "3" }, + { tag: "Business and activity", publishNumber: "8", popularity: "70%", trimester: "1" }, + { tag: "Safety and Well-being", publishNumber: "4", popularity: "11%", trimester: "2" }, + { tag: "Environment and Sustainability", publishNumber: "5", popularity: "20%", trimester: "2" }, + { tag: "Business and activity", publishNumber: "8", popularity: "60%", trimester: "1" }, ]; - await UseCase.insertMany(dummyData); + await UseCase.insertMany(caseStudies); console.log('Dummy data inserted.'); - // Mock req and res objects - const req = { + // Test case 1: Fetch use case statistics with filters + const reqStats = { method: 'GET', - query: { stats: 'true' } + query: { stats: 'true', tag: 'Environment and Sustainability', trimester: '2' } }; - const res = { + const resStats = { status: (statusCode) => { - res.statusCode = statusCode; - return res; + resStats.statusCode = statusCode; + return resStats; }, json: (data) => { - console.log('Response:', data); + console.log('Response for stats request:', data); }, end: (message) => { console.log('Response ended:', message); @@ -40,11 +46,39 @@ async function main() { try { console.log('Fetching use case statistics...'); - await handleRequest(req, res); - console.log('Operation completed.'); + await handleRequest(reqStats, resStats); } catch (error) { - console.error('Error executing request:', error.message); + console.error('Error executing stats request:', error.message); } + + // Test case 2: Fetch use case count by trimester + const reqCount = { + method: 'GET', + query: {} // No filters for counting by trimester + }; + + const resCount = { + status: (statusCode) => { + resCount.statusCode = statusCode; + return resCount; + }, + json: (data) => { + console.log('Response for count request:', data); + }, + end: (message) => { + console.log('Response ended:', message); + }, + statusCode: null + }; + + try { + console.log('Fetching use case count by trimester...'); + await handleRequest(reqCount, resCount); + } catch (error) { + console.error('Error executing count request:', error.message); + } + + console.log('Operation completed.'); } // Execute the main function if this module is run directly From 13a8bae81463f87987323147960fa9dc9abc37c1 Mon Sep 17 00:00:00 2001 From: s223456323 Date: Tue, 17 Sep 2024 08:30:58 +1000 Subject: [PATCH 2/2] update statistics changes and update statistics page to use data from api --- .../src/app/[locale]/statistics/page.tsx | 99 +++++++++++------ next_webapp/src/app/api/statistics/route.ts | 44 ++++++++ next_webapp/src/mongodb/CaseStudies.js | 36 +++++++ .../src/mongodb/{UseCase.js => CaseStudy.js} | 12 ++- next_webapp/src/mongodb/UseCases.js | 100 ------------------ next_webapp/src/mongodb/test-stats.js | 41 ++----- 6 files changed, 158 insertions(+), 174 deletions(-) create mode 100644 next_webapp/src/app/api/statistics/route.ts create mode 100644 next_webapp/src/mongodb/CaseStudies.js rename next_webapp/src/mongodb/{UseCase.js => CaseStudy.js} (72%) delete mode 100644 next_webapp/src/mongodb/UseCases.js diff --git a/next_webapp/src/app/[locale]/statistics/page.tsx b/next_webapp/src/app/[locale]/statistics/page.tsx index 0f32bda77..778b055be 100644 --- a/next_webapp/src/app/[locale]/statistics/page.tsx +++ b/next_webapp/src/app/[locale]/statistics/page.tsx @@ -1,18 +1,11 @@ "use client"; -import React, { useState, useEffect } from "react"; +import React, {useEffect, useState} from "react"; import Header from "../../../components/Header"; import Footer from "../../../components/Footer"; -import { useTranslations } from "next-intl"; -import { - Chart as ChartJS, - CategoryScale, - LinearScale, - BarElement, - Title, - Tooltip, - Legend, -} from "chart.js"; -import { Bar } from "react-chartjs-2"; +import {useTranslations} from "next-intl"; +import {BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip,} from "chart.js"; +import {Bar} from "react-chartjs-2"; +import {CATEGORY, SEARCH_MODE, SearchParams} from "@/app/types"; ChartJS.register( CategoryScale, @@ -23,39 +16,75 @@ ChartJS.register( Legend ); -const Statistics = () => { - // Dummy Array - const caseStudies = [ - { id: 1, tag: "Safety and Well-being", publishNumber: "4", popularity: "11%", trimester: "1" }, - { id: 2, tag: "Environment and Sustainability", publishNumber: "5", popularity: "40%", trimester: "2" }, - { id: 3, tag: "Business and activity", publishNumber: "8", popularity: "90%", trimester: "3" }, - { id: 4, tag: "Safety and Well-being", publishNumber: "4", popularity: "11%", trimester: "2" }, - { id: 5, tag: "Environment and Sustainability", publishNumber: "5", popularity: "90%", trimester: "3" }, - { id: 6, tag: "Business and activity", publishNumber: "8", popularity: "70%", trimester: "1" }, - { id: 7, tag: "Safety and Well-being", publishNumber: "4", popularity: "11%", trimester: "2" }, - { id: 8, tag: "Environment and Sustainability", publishNumber: "5", popularity: "20%", trimester: "2" }, - { id: 9, tag: "Business and activity", publishNumber: "8", popularity: "60%", trimester: "1" }, - ]; +async function searchStatistics(searchParams: SearchParams) { + const response = await fetch("/api/statistics", { + method: "GET", + headers: { + "Content-Type": "application/json", + } + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); +} + + +const Statistics = () => { + const [caseStudies, setCaseStudies] = useState([]); // State for storing the filtered results and all filters const [filteredStudies, setFilteredStudies] = useState(caseStudies); + + useEffect(() => { + fetchStatistics() + }, []) + + const fetchStatistics = async () => { + try { + const data = await searchStatistics({searchTerm: "", + searchMode: SEARCH_MODE.TITLE, + category: CATEGORY.EV}); + setCaseStudies(data); + console.log('data received! ' + data.toString()); + } catch (error) { + console.log('request called!'); + } finally { + console.log('request called finally!'); + } + }; + const [tagFilter, setTagFilter] = useState(""); const [trimesterFilter, setTrimesterFilter] = useState(""); const [pagefilter, setPageFilter] = useState("5"); const [search, setSearchTerm] = useState(""); + // Effect to handle filtering based on tag and trimester + useEffect(() => { + let filtered = caseStudies; + if (tagFilter) { + filtered = filtered.filter((study: {tag: string}) => study.tag === tagFilter); + } + if (trimesterFilter) { + filtered = filtered.filter((study: {trimester: string}) => study.trimester === trimesterFilter); + } + setFilteredStudies(filtered); + }, [tagFilter, trimesterFilter]); + // Distinct tags for the dropdown - const tags = Array.from(new Set(caseStudies.map((study) => study.tag))); - const trimesters = Array.from(new Set(caseStudies.map((study) => study.trimester))); + const tags = Array.from(new Set(caseStudies.map((study: {tag: string}) => study.tag))); + // Distinct trimesters for the dropdown + const trimesters = Array.from(new Set(caseStudies.map((study: {trimester: string}) => study.trimester))); // Effect to handle filtering based on tag and trimester useEffect(() => { let filtered = caseStudies; if (tagFilter) { - filtered = filtered.filter((study) => study.tag === tagFilter); + filtered = filtered.filter((study: {tag: string}) => study.tag === tagFilter); } if (trimesterFilter) { - filtered = filtered.filter((study) => study.trimester === trimesterFilter); + filtered = filtered.filter((study: {trimester: string}) => study.trimester === trimesterFilter); } setFilteredStudies(filtered); }, [tagFilter, trimesterFilter]); @@ -68,7 +97,7 @@ const Statistics = () => { const npage = Math.ceil(filteredStudies.length / recordsPage); // Sort caseStudies by popularity - const sortedStudiesByPopularity = [...caseStudies].sort((a, b) => { + const sortedStudiesByPopularity = [...caseStudies].sort((a: {popularity: string}, b: {popularity: string}) => { const popularityA = parseFloat(a.popularity.replace('%', '')); const popularityB = parseFloat(b.popularity.replace('%', '')); return popularityB - popularityA; // Descending order @@ -76,9 +105,9 @@ const Statistics = () => { // Counting the values of trimester to plot on the graph - const tri1 = caseStudies.filter((item) => item.trimester === "1").length; - const tri2 = caseStudies.filter((item) => item.trimester === "2").length; - const tri3 = caseStudies.filter((item) => item.trimester === "3").length; + const tri1 = caseStudies.filter((item: {trimester: string}) => item.trimester === "1").length; + const tri2 = caseStudies.filter((item: {trimester: string}) => item.trimester === "2").length; + const tri3 = caseStudies.filter((item: {trimester: string}) => item.trimester === "3").length; // Store the required variables for plotting the graph const data1 = { @@ -229,12 +258,12 @@ const Statistics = () => { {records - .filter((item) => { + .filter((item: {tag: string}) => { return search.toLowerCase() === "" ? item : item.tag.toLowerCase().includes(search); }) - .map((study, index) => ( + .map((study: {id: string, tag: string, publishNumber: string, popularity: string }, index) => ( { - resStats.statusCode = statusCode; - return resStats; - }, - json: (data) => { - console.log('Response for stats request:', data); - }, - end: (message) => { - console.log('Response ended:', message); - }, - statusCode: null - }; - - try { - console.log('Fetching use case statistics...'); - await handleRequest(reqStats, resStats); - } catch (error) { - console.error('Error executing stats request:', error.message); - } - - // Test case 2: Fetch use case count by trimester + //Fetch all use cases const reqCount = { method: 'GET', - query: {} // No filters for counting by trimester + query: {} }; const resCount = {