Skip to content

Commit

Permalink
[WIP] Trying things
Browse files Browse the repository at this point in the history
  • Loading branch information
Gavriil-Tzortzakis committed Nov 2, 2024
1 parent 9ec7ce3 commit 4ba3261
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 10 deletions.
22 changes: 22 additions & 0 deletions shared/locales/en/website-responses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Survey Responses",
"onboarding": {
"title": "Onboarding Survey",
"description": "Filled out once before recipient is joining the program"
},
"checkin": {
"title": "Check-in Survey",
"description": "Filled out every 6 months while recipient is in the program"
},
"offboarding": {
"title": "Offboarding Survey",
"description": "Filled out once when recipient is finishing the program"
},
"offboarded-checkin": {
"title": "Follow-up Survey",
"description": "Filled out every 6 months after recipient left the program"
}



}
70 changes: 70 additions & 0 deletions shared/src/utils/stats/SurveyStatsCalculator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import _ from 'lodash';
import { FirestoreAdmin } from '../../firebase/admin/FirestoreAdmin';
import { Recipient, RECIPIENT_FIRESTORE_PATH } from '../../types/recipient';
import { Survey, SURVEY_FIRETORE_PATH, SurveyQuestionnaire, SurveyStatus } from '../../types/survey';

export interface SurveyStats {
total: number;
type: SurveyQuestionnaire;
}

export interface SurveyAnswersByType {
answers: any[];
}

export class SurveyStatsCalculator {
private readonly _data: SurveyStats[];
private readonly _aggregatedData: { [key: string]: { [key: string]: SurveyAnswersByType } };

private constructor(
data: SurveyStats[],
aggregatedData: {
[key: string]: { [key: string]: SurveyAnswersByType };
},
) {
this._data = data;
this._aggregatedData = aggregatedData;
}

/**
* @param firestoreAdmin
*/
static async build(firestoreAdmin: FirestoreAdmin): Promise<SurveyStatsCalculator> {
const recipients = await firestoreAdmin.collection<Recipient>(RECIPIENT_FIRESTORE_PATH).get();
let documents = await Promise.all(
recipients.docs
.filter((recipient) => !recipient.get('test_recipient'))
.map(async (recipient) => {
return await firestoreAdmin
.collection<Survey>(`${RECIPIENT_FIRESTORE_PATH}/${recipient.id}/${SURVEY_FIRETORE_PATH}`)
.get();
}),
);

let surveysData = documents.flatMap((snapshot) => snapshot.docs).map((survey) => survey.data());

let aggregatedData: { [key: string]: { [key: string]: SurveyAnswersByType } } = {};
const typeCounts: { [type: string]: number } = {};
surveysData.forEach((item) => {
if (item.status === SurveyStatus.Completed) {
typeCounts[item.questionnaire] = (typeCounts[item.questionnaire] || 0) + 1;
for (const [key, value] of Object.entries(item.data)) {
aggregatedData[item.questionnaire] = aggregatedData[item.questionnaire] || {};
aggregatedData[item.questionnaire][key] = aggregatedData[item.questionnaire][key] || { answers: [] };
aggregatedData[item.questionnaire][key].answers.push(value);
}
}
});
const data = Object.entries(typeCounts).map(([type, total]) => ({ type, total }) as SurveyStats);

return new SurveyStatsCalculator(data, aggregatedData);
}

get data(): SurveyStats[] {
return this._data;
}

get aggregatedData(): { [key: string]: { [key: string]: SurveyAnswersByType } } {
return this._aggregatedData;
}
}
61 changes: 51 additions & 10 deletions website/src/app/[lang]/[region]/(website)/survey/responses/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,58 @@
import { DefaultLayoutProps, DefaultPageProps } from '@/app/[lang]/[region]';
import { getMetadata } from '@/metadata';
import { firestoreAdmin } from '@/firebase-admin';
import { SurveyStatsCalculator } from '@socialincome/shared/src/utils/stats/SurveyStatsCalculator';
import { BaseContainer, Card, CardTitle, Typography } from '@socialincome/ui';
import { Translator } from '@socialincome/shared/src/utils/i18n';
import { DefaultPageProps } from '@/app/[lang]/[region]';
import { SurveyQuestionnaire } from '@socialincome/shared/src/types/survey';

export async function generateMetadata({ params }: DefaultLayoutProps) {
return getMetadata(params.lang, 'website-login');
}
export const revalidate = 3600; // update once an hour
export default async function Page({ params: { lang } }: DefaultPageProps) {

export default async function Page({ params }: DefaultPageProps) {
const translator = await Translator.getInstance({ language: params.lang, namespaces: ['website-login'] });
const surveyStatsCalculator = await SurveyStatsCalculator.build(firestoreAdmin);
const temp = surveyStatsCalculator.data;
const allSurveyData = Object.values(SurveyQuestionnaire).map((it) => temp.find((survey) => survey.type == it));
const data = surveyStatsCalculator.aggregatedData;
const translator = await Translator.getInstance({
language: lang,
namespaces: ['website-responses'],
});
let selectedSurvey = SurveyQuestionnaire.Onboarding;

return (
<div className="min-h-screen-navbar mx-auto flex max-w-lg flex-col">
hello
</div>
<BaseContainer className="mx-auto flex max-w-3xl flex-col space-y-12">
<Typography size="4xl" weight="bold">
{translator.t('title')}
</Typography>
<div className="flex flex-col space-y-2 py-4">
<div className="mt-2 grid grid-cols-4 gap-2">
{allSurveyData.map(
surveyData =>
surveyData && (
<Card key={surveyData.type} className="p-2">
<CardTitle className="text py-2">{translator.t(surveyData.type + '.title')}</CardTitle>

<Typography className="mt-2">{translator.t(surveyData.type + '.description')}</Typography>
<Typography className="mt-3">{surveyData.total} data points</Typography>
</Card>
),
)}
</div>
</div>
<div className="flex flex-col">
<div className="mt-2 grid grid-cols-1 gap-2">
{Object.keys(data[selectedSurvey]).map(
(key) =>
(
<Card key={key} className="p-2">
<CardTitle className="text py-2">{translator.t(key + '.title')}</CardTitle>

<Typography className="mt-2">{JSON.stringify(data[selectedSurvey][key].answers)}</Typography>
<Typography className="mt-3">{data[selectedSurvey][key].answers.length} answers</Typography>
</Card>
)
)}
</div>
</div>
</BaseContainer>
);
}

0 comments on commit 4ba3261

Please sign in to comment.