Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
linxiaoxin committed Aug 14, 2024
2 parents 3133792 + a3fbfb7 commit 8f4f23d
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 149 deletions.
10 changes: 5 additions & 5 deletions .env
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
NEXT_PUBLIC_COGNITO_CLIENT_ID=1234
NEXT_PUBLIC_COGNITO_URL =https://quemistry.auth.ap-southeast-1.amazoncognito.com
NEXT_PUBLIC_COGNITO_CLIENT_ID = 1234
NEXT_PUBLIC_COGNITO_URL = https://quemistry.auth.ap-southeast-1.amazoncognito.com
NEXT_PUBLIC_IDP_AuthorizeEndpoint = $NEXT_PUBLIC_COGNITO_URL/oauth2/authorize
NEXT_PUBLIC_IDP_Tokendpoint = $NEXT_PUBLIC_COGNITO_URL/oauth2/token
NEXT_PUBLIC_QUEMISTRY_DOMAIN =https://dkraju438qs82.cloudfront.net
NEXT_PUBLIC_QUEMISTRY_DOMAIN = https://dkraju438qs82.cloudfront.net
NEXT_PUBLIC_RedirectUrl = $NEXT_PUBLIC_QUEMISTRY_DOMAIN/auth/google
NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL=https://b4jba6xq87.execute-api.ap-southeast-1.amazonaws.com/Staging
NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL= https://b4jba6xq87.execute-api.ap-southeast-1.amazonaws.com/Staging
NEXT_PUBLIC_QUEMISTRY_AUTH_URL = $NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL/auth
NEXT_PUBLIC_QUEMISTRY_QUESTIONS_URL = $NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL/questions
NEXT_PUBLIC_QUEMISTRY_USER_URL = $NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL/user
NEXT_PUBLIC_QUEMISTRY_CLASS_URL = $NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL/class
NEXT_PUBLIC_QUEMISTRY_QUIZZES_URL = $NEXT_PUBLIC_QUEMISTRY_GATEWAY_URL/quizzes
145 changes: 35 additions & 110 deletions app/(main)/classes/page.tsx
Original file line number Diff line number Diff line change
@@ -1,147 +1,72 @@
/* eslint-disable @next/next/no-img-element */
'use client';
import { Button } from 'primereact/button';
import React, { Fragment, useContext, useEffect, useRef, useState } from 'react';
import { ChartOptions } from 'chart.js';
import React, { Fragment, useState } from 'react';
import { Dialog } from 'primereact/dialog';
import { InputText } from 'primereact/inputtext';
import { LayoutContext } from '@/layout/context/layoutcontext';
import { UserService } from '../../../service/UserService';
import { UserService } from '@/service/UserService';


const Classes = () => {
const [addClass, setAddClass] = useState(false);
const [newClassCode, setNewClassCode] = useState('');
const [newClassDescription, setNewClassDescription] = useState('');
const [newClassEducationLevel, setNewClassEducationLevel] = useState('');
const [newClassSubject, setNewClassSubject] = useState('');

const { layoutConfig } = useContext(LayoutContext);
interface ClassMap {
descriptionName: string;
apiName: string;
defaultValue: string;
value: string;
setValue: React.Dispatch<React.SetStateAction<string>>;
}

const useGenerateClassMap = (descriptionName: string, apiName: string, defaultValue: string): ClassMap => {
const [value, setValue] = useState(defaultValue);
return { descriptionName, apiName, defaultValue, value, setValue };
}

const classMapList: ClassMap[] = [
useGenerateClassMap('Class Code', 'code', ''),
useGenerateClassMap('Class Description', 'description', ''),
useGenerateClassMap('Class Education Level', 'educationLevel', ''),
useGenerateClassMap('Class Subject', 'subject', 'Chemistry')
];

const clearNewClass = () => {
setAddClass(false);
setNewClassCode('');
setNewClassDescription('');
setNewClassEducationLevel('');
setNewClassSubject('');
};
const applyLightTheme = () => {
const lineOptions: ChartOptions = {
plugins: {
legend: {
labels: {
color: '#495057'
}
}
},
scales: {
x: {
ticks: {
color: '#495057'
},
grid: {
color: '#ebedef'
}
},
y: {
ticks: {
color: '#495057'
},
grid: {
color: '#ebedef'
}
}
}
};
};

const applyDarkTheme = () => {
const lineOptions = {
plugins: {
legend: {
labels: {
color: '#ebedef'
}
}
},
scales: {
x: {
ticks: {
color: '#ebedef'
},
grid: {
color: 'rgba(160, 167, 181, .3)'
}
},
y: {
ticks: {
color: '#ebedef'
},
grid: {
color: 'rgba(160, 167, 181, .3)'
}
}
}
};
classMapList.forEach(({ setValue, defaultValue }) => setValue(defaultValue));
};

const saveClass = async () => {
const newClass: Class = {
code: newClassCode,
description: newClassDescription,
educationLevel: newClassEducationLevel,
subject: newClassSubject
};

await UserService.addClass("user-id", newClass)
await UserService.addClass(classMapList.reduce((result, { apiName, value }) => ({ ...result, [apiName]: value }), {}) as Class);
clearNewClass();
}

const addClassFooter = (
<div>
<Button label="Cancel" icon="pi pi-times" onClick={() => clearNewClass()} className="p-button-text" />
<Button label="Save" icon="pi pi-save" onClick={() => saveClass()} autoFocus />
<Button label='Cancel' icon='pi pi-times' onClick={clearNewClass} className='p-button-text' />
<Button label='Save' icon='pi pi-save' onClick={saveClass} autoFocus />
</div>
);

const renderField = (labelTextName: string, value: string, onChange: (e: React.ChangeEvent<HTMLInputElement>) => void) => (
<div className="field grid">
<label htmlFor={labelTextName} className="col-12 mb-2 md:col-2 md:mb-0">
<div className='field grid'>
<label htmlFor={labelTextName} className='col-12 mb-2 md:col-2 md:mb-0'>
{labelTextName}
</label>
<div className="col-12 md:col-10">
<div className='col-12 md:col-10'>
<InputText placeholder={labelTextName} style={{ width: '30vw' }} value={value} onChange={onChange} />
</div>
</div>
);

useEffect(() => {
if (layoutConfig.colorScheme === 'light') {
applyLightTheme();
} else {
applyDarkTheme();
}
}, [layoutConfig.colorScheme]);

return (
<div className="grid">
<div className="col-12 xl:col-6">
<div className="card">
<div className='grid'>
<div className='col-12 xl:col-6'>
<div className='card'>
<Fragment>
<Button label="New" icon="pi pi-plus" onClick={(e) => setAddClass(true)} />
<Button label='New' icon='pi pi-plus' onClick={() => setAddClass(true)} />
</Fragment>
<Dialog
header="Add Class"
style={{ width: '50vw' }}
visible={addClass}
onHide={() => {
addClass && clearNewClass();
}}
footer={addClassFooter}
>
{renderField('Class Code', newClassCode, (e) => setNewClassCode(e.target.value))}
{renderField('Class Description', newClassDescription, (e) => setNewClassDescription(e.target.value))}
{renderField('Class Education Level', newClassEducationLevel, (e) => setNewClassEducationLevel(e.target.value))}
{renderField('Class Subject', newClassSubject, (e) => setNewClassSubject(e.target.value))}
<Dialog header='Add Class' style={{ width: '50vw' }} visible={addClass} onHide={() => { addClass && clearNewClass(); }} footer={addClassFooter}>
{classMapList.map(({ descriptionName, value, setValue }) => renderField(descriptionName, value, ({ target }) => setValue(target.value)))}
</Dialog>
<h5>Manage Classes</h5>
</div>
Expand Down
67 changes: 47 additions & 20 deletions app/(main)/questions/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const EditQuestion = () => {
const [addedOptions, setAddedOptions] = useState<Questions.Option[]>([]);
const [stem, setStem] = useState<string>('');
const [answer, setAnswer] = useState<string>('');
const [explanation, setExplanation] = useState<string>('');
const [isAnswer, setIsAnswer] = useState<boolean>(false);
const [listOfTopics, setListOfTopics] = useState<Questions.Topic[]>([]);
const [showOptionDialog, setShowOptionDialog] = useState<boolean>(false);
Expand Down Expand Up @@ -51,8 +52,15 @@ const EditQuestion = () => {

const optionsItemTemplate = (option: Questions.Option) => {
return(
<Editor readOnly value={option.text} showHeader={false}>
<>
<div style={{margin:'1em 0em 0.3em 0.1em', fontSize:'.9em'}}>option</div>
<Editor style={{marginBottom:'0.5em'}} readOnly value={option.text} showHeader={false}>
</Editor>
<div></div>
<div style={{margin:'1em 0em 0.3em 0.1em', fontSize:'.9em'}}>explanation</div>
<Editor readOnly value={option.explanation} showHeader={false}>
</Editor>
</>
)
}
const optionItemActionTemplate = (option: Questions.Option) => {
Expand Down Expand Up @@ -87,7 +95,8 @@ const EditQuestion = () => {
return {
no: index + 1,
text: option.text,
isAnswer: option.isAnswer
isAnswer: option.isAnswer,
explanation: option.explanation
}
})
setAddedOptions(reOrderedOptions);
Expand All @@ -100,7 +109,8 @@ const EditQuestion = () => {
return {
no: option.no,
text: option.text,
isAnswer: option.no === selectedNo
isAnswer: option.no === selectedNo,
explanation: option.explanation
}
})
}
Expand All @@ -116,17 +126,20 @@ const EditQuestion = () => {
return {
no: index + 1,
text: option.text,
isAnswer: option.isAnswer
isAnswer: option.isAnswer,
explanation: option.explanation
}
})
options.push({
no: options.length +1,
text: answer,
isAnswer: isAnswer
text: answer,
isAnswer: isAnswer,
explanation: explanation
})

setAddedOptions(options);
setAnswer("");
setExplanation("");
setIsAnswer(false);
setShowOptionDialog(false);
};
Expand Down Expand Up @@ -218,10 +231,10 @@ const EditQuestion = () => {
<label htmlFor="ms-skills">Skills</label>
</FloatLabel> */}
</div>
<div className="col-12">
Other information like publised date
</div>
<div className="col-12">
{/* <div className="col-12">
<Button label="Next" onClick={()=> {setActiveTab(1)}}></Button>
</div> */}
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className="col-12">
<Button label="Next" onClick={()=> {setActiveTab(1)}}></Button>
</div>
</div>
Expand All @@ -233,20 +246,28 @@ const EditQuestion = () => {
<Editor value={stem} onTextChange={(e: EditorTextChangeEvent) => setStem(e.htmlValue || '')} style={{ height: '320px' }} />
</div>
</div>
<div className="col-12">
{/* <div className="col-12">
<Button label="Next" onClick={()=> {setActiveTab(2)}}></Button>
</div> */}
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className="col-12">
<Button label="Next" onClick={()=> {setActiveTab(2)}}></Button>
</div>
</TabPanel>
<TabPanel header="Options">
<Dialog visible={showOptionDialog} style={{ width: '80vw' }} modal={false} position="bottom" onHide={() => {if (!showOptionDialog) return; setShowOptionDialog(false); }}>
<div className="grid">
<div className="col-10">Fill in the options of the question and indicate answer.</div>
<div className="col-2">
<Button label="Add" onClick={handleOnClickAdd} size="small"/>
</div>
<div className="col-10">Add an option for the question</div>

<div className="col-12">
<Editor value={answer} onTextChange={(e: EditorTextChangeEvent) => setAnswer(e.htmlValue || '')} style={{ height: '100px' }} />
</div>
<div className="col-10">Explain why this option is correct or wrong</div>
<div className="col-12">
<Editor value={explanation} onTextChange={(e: EditorTextChangeEvent) => setExplanation(e.htmlValue || '')} style={{ height: '100px' }} />
</div>
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className="col-12">
<Button label="Add" onClick={handleOnClickAdd} size="small"/>
</div>
<div className="col-10">
</div>
</div>
Expand All @@ -262,25 +283,31 @@ const EditQuestion = () => {
<Column style={{ width: '5%' }} body={optionItemActionTemplate}></Column>
</DataTable>
</div>
<div className="col-12">
{/* <div className="col-12">
<Button label="Next" onClick={()=> {setActiveTab(3)}}></Button>
</div> */}
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className="col-12">
<Button label="Next" onClick={()=> {setActiveTab(3)}}></Button>
</div>
</div>
</div>
</TabPanel>
<TabPanel header="Review">
<div className="grid">
<div className="col-12">
<Editor readOnly value={stem} showHeader={false} style={{ height: '400px' }}>
<Editor readOnly value={stem} showHeader={false} style={{ height: '320px' }}>
</Editor>
</div>
<div className="col-12">
<DataTable value={addedOptions} emptyMessage="No options added">
<Column field="no" style={{ width: '5%' }}></Column>
<Column field="no" style={{ width: '5%'}}></Column>
<Column style={{ width: '90%' }} body={optionsItemTemplate}></Column>
</DataTable>
</div>
<div className="col-9 md:col-11">&nbsp;</div>
<div className="col-1">
{/* <div className="col-1">
<Button label="Done" onClick={handleOnClickDone}></Button>
</div> */}
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className="col-12">
<Button label="Done" onClick={handleOnClickDone}></Button>
</div>

Expand Down
4 changes: 2 additions & 2 deletions app/(main)/questions/searchlist/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ const QuestioSearchList = () => {
<div className="col-12 md:col-6"><label>Topics: </label>{topics}</div>
<div className="col-12 md:col-6"><label>Skills: </label>{skills}</div>
<div className="col-12 md:col-3"><label>Status: </label>{rowData.status}</div>
<div className="col-12 md:col-3"><label>Published on: </label>{formatDate(rowData.publishedOn)}</div>
<div className="col-12 md:col-6"><label>Published by: </label>{rowData.publishedBy}</div>
<div className="col-12 md:col-3"><label>Created on: </label>{formatDate(rowData.createdTs)}</div>
<div className="col-12 md:col-6"><label>Created by: </label>{rowData.createdBy}</div>
<div className="col-12 md:col-10">&nbsp;</div>
<div className="col-12 md:col-2">
<span></span>
Expand Down
16 changes: 7 additions & 9 deletions service/UserService.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
const userServiceUrl = process.env.NEXT_PUBLIC_QUEMISTRY_USER_URL || ''
const saveUserServiceUrl =`${userServiceUrl}/v1/class`
const classUrl = process.env.NEXT_PUBLIC_QUEMISTRY_CLASS_URL || ''

export const UserService = {
async addClass(userId: string, data: Class) {
console.log("calling saveClass ", saveUserServiceUrl);
const res = await fetch(saveUserServiceUrl, {
async addClass(data: Class) {
const res = await fetch(classUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-USER-ID': userId
'Cookie': 'QUESESSION=f1d94def-900a-4643-bce9-df86cc8b1d7c'
},
credentials: "include",
credentials: 'include',
body: JSON.stringify(data)
});
console.log("res", res);
console.log('res', res);
}
}
};
Loading

0 comments on commit 8f4f23d

Please sign in to comment.