Skip to content

Commit

Permalink
feat: batch student progress modal
Browse files Browse the repository at this point in the history
  • Loading branch information
pateljannat committed Dec 19, 2024
1 parent b48e007 commit 4d18580
Show file tree
Hide file tree
Showing 7 changed files with 422 additions and 473 deletions.
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@editorjs/simple-image": "^1.6.0",
"@editorjs/table": "^2.4.2",
"ace-builds": "^1.36.2",
"apexcharts": "^4.3.0",
"chart.js": "^4.4.1",
"codemirror-editor-vue3": "^2.8.0",
"dayjs": "^1.11.6",
Expand All @@ -35,6 +36,7 @@
"vue-chartjs": "^5.3.0",
"vue-draggable-next": "^2.2.1",
"vue-router": "^4.0.12",
"vue3-apexcharts": "^1.8.0",
"vuedraggable": "4.1.0"
},
"devDependencies": {
Expand Down
274 changes: 223 additions & 51 deletions frontend/src/components/BatchStudents.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
<template>
<div class="flex items-center justify-between mb-4">
<div class="text-lg font-semibold">
{{ __('Students') }}
<div>
<!-- <Bar v-if="chartData" :data="chartData" :options="chartOptions" /> -->
<ApexChart
v-if="chartData"
:options="chartOptions"
:series="chartData"
type="bar"
height="350"
/>
<div class="flex items-center justify-between mb-4">
<div class="text-lg font-semibold">
{{ __('Students') }}
</div>
<Button @click="openStudentModal()">
<template #prefix>
<Plus class="h-4 w-4" />
</template>
{{ __('Add') }}
</Button>
</div>
<Button @click="openStudentModal()">
<template #prefix>
<Plus class="h-4 w-4" />
</template>
{{ __('Add') }}
</Button>
</div>
<div v-if="students.data?.length">
<ListView
:columns="getStudentColumns()"
:rows="students.data"
row-key="name"
:options="{ showTooltip: false }"
:options="{
showTooltip: false,
onRowClick: (row) => {
openStudentProgressModal(row)
},
}"
>
<ListHeader
class="mb-2 grid items-center space-x-4 rounded bg-gray-100 p-2"
Expand Down Expand Up @@ -48,10 +63,16 @@
/>
</div>
</template>
<div v-if="column.key == 'courses'">
<div
v-if="column.key == 'progress'"
class="flex items-center space-x-4 w-full"
>
<ProgressBar :progress="row[column.key]" size="sm" />
</div>
<div v-else>
{{ row[column.key] }}
</div>
<div v-else-if="column.icon == 'book-open'">
<!-- <div v-else-if="column.icon == 'book-open'">
{{ Math.ceil(row.courses[column.key]) }}
</div>
<div v-else-if="column.icon == 'help-circle'">
Expand All @@ -63,7 +84,7 @@
{{ row.assessments[column.key] }}
</Badge>
<div v-else>{{ parseInt(row.assessments[column.key]) }}</div>
</div>
</div> -->
</ListRowItem>
</template>
</ListRow>
Expand All @@ -90,11 +111,14 @@
v-model="showStudentModal"
v-model:reloadStudents="students"
/>
<BatchStudentProgress
:student="selectedStudent"
v-model="showStudentProgressModal"
/>
</template>
<script setup>
import {
Avatar,
Badge,
Button,
createResource,
FeatherIcon,
Expand All @@ -107,11 +131,38 @@ import {
ListRowItem,
} from 'frappe-ui'
import { Trash2, Plus } from 'lucide-vue-next'
import { ref } from 'vue'
import { computed, ref } from 'vue'
import StudentModal from '@/components/Modals/StudentModal.vue'
import { showToast } from '@/utils'
import ProgressBar from '@/components/ProgressBar.vue'
import BatchStudentProgress from '@/components/Modals/BatchStudentProgress.vue'
import { Bar } from 'vue-chartjs'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
BarElement,
CategoryScale,
LinearScale,
Filler,
} from 'chart.js'
ChartJS.register(
Title,
Tooltip,
Legend,
BarElement,
CategoryScale,
LinearScale,
Filler
)
import ApexChart from 'vue3-apexcharts'
const showStudentModal = ref(false)
const showStudentProgressModal = ref(false)
const selectedStudent = ref(null)
const chartData = ref(null)
const chartOptions = ref(null)
const props = defineProps({
batch: {
Expand All @@ -127,50 +178,47 @@ const students = createResource({
batch: props.batch,
},
auto: true,
onSuccess(data) {
chartData.value = getChartData()
console.log(chartData.value)
},
})
const getStudentColumns = () => {
let columns = [
{
label: 'Full Name',
key: 'full_name',
width: '20rem',
icon: 'user',
},
{
label: 'Progress',
key: 'progress',
width: '10rem',
icon: 'activity',
},
{
label: 'Last Active',
key: 'last_active',
width: '15rem',
align: 'center',
icon: 'clock',
},
]
if (students.data?.[0].assessments) {
Object.keys(students.data?.[0].assessments).forEach((assessment) => {
columns.push({
label: assessment,
key: assessment,
width: '10rem',
icon: 'help-circle',
align: isAssignment(students.data?.[0].assessments[assessment])
? 'left'
: 'center',
})
})
}
if (students.data?.[0].courses) {
Object.keys(students.data?.[0].courses).forEach((course) => {
columns.push({
label: course,
key: course,
width: '10rem',
icon: 'book-open',
align: 'center',
})
})
}
return columns
}
const openStudentModal = () => {
showStudentModal.value = true
}
const openStudentProgressModal = (row) => {
showStudentProgressModal.value = true
selectedStudent.value = row
}
const deleteStudents = createResource({
url: 'lms.lms.api.delete_documents',
makeParams(values) {
Expand All @@ -196,17 +244,141 @@ const removeStudents = (selections, unselectAll) => {
)
}
const getStatusTheme = (status) => {
if (status === 'Pass') {
return 'green'
} else if (status == 'Not Graded') {
return 'orange'
} else {
return 'red'
}
const getChartData = () => {
console.log('called')
let categories = {}
// Initialize categories with categories
Object.keys(students.data?.[0].courses).forEach((course) => {
categories[course] = {
value: 0,
type: 'course',
}
})
Object.keys(students.data?.[0].assessments).forEach((assessment) => {
categories[assessment] = {
value: 0,
type: 'assessment',
}
})
// Populate data
students.data.forEach((student) => {
Object.keys(student.courses).forEach((course) => {
if (student.courses[course] === 100) {
categories[course].value += 1
}
})
Object.keys(student.assessments).forEach((assessment) => {
if (student.assessments[assessment] === 100) {
categories[assessment].value += 1
}
})
})
// Transform data for ApexCharts
console.log(Object.values(categories).map((item) => item.value))
chartOptions.value = getChartOptions(categories)
return [
{
name: __('Student Progress'),
data: Object.values(categories).map((item) => item.value),
/* colors: Object.values(categories).map(item =>
item.type === 'course' ? courseColor : assessmentColor
), */
},
]
}
const isAssignment = (value) => {
return isNaN(value)
/* const chartOptions = computed(() => {
return {
responsive: true,
fill: true,
scales: {
x: {
ticks: {
maxRotation: 0,
minRotation: 0,
autoSkip: false,
}
},
y: {
beginAtZero: true,
max: students.data?.length,
ticks: {
stepSize: 5,
},
},
},
plugins: {
legends: {
display: false,
title: {
text: __("Student Progress 1111"),
}
},
title: {
display: true,
text: __("Student Progress"),
font: {
size: 14,
weight: '500',
},
color: '#171717',
}
}
}
}) */
const chartSeries = ref([
{
name: 'Courses',
data: [20, 30, 50], // Example data for courses
},
{
name: 'Assessments',
data: [10, 40, 60], // Example data for assessments
},
])
const getChartOptions = (categories) => {
const courseColor = '#3498db' // Blue for courses
const assessmentColor = '#e74c3c' // Red for assessments
return {
chart: {
type: 'bar',
height: 350,
},
plotOptions: {
bar: {
distributed: true, // Allows individual bar colors
borderRadius: 0,
horizontal: false, // Set to true for horizontal bars
columnWidth: '30%',
},
},
colors: Object.values(categories).map((item) =>
item.type === 'course' ? courseColor : assessmentColor
),
legends: {
show: true,
},
xaxis: {
categories: Object.keys(categories),
labels: {
style: {
fontSize: '10px',
},
rotate: 0,
formatter: function (value) {
console.log(value)
return value.length > 20 ? `${value.substring(0, 20)}...` : value // Trim long labels
},
},
},
}
}
</script>
Loading

0 comments on commit 4d18580

Please sign in to comment.