Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style(apps/analytics): organize performance analytics in tab structure #4404

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button } from '@uzh-bf/design-system'
import { Button, FormLabel } from '@uzh-bf/design-system'
import { useTranslations } from 'next-intl'
import { SetStateAction } from 'react'

Expand All @@ -12,25 +12,32 @@ function ActivitiesElementsSwitch({
const t = useTranslations()

return (
<div className="flex flex-row">
<Button
basic
onClick={() => setType('activity')}
className={{
root: `py-0.25 rounded-l border !border-r-0 border-solid px-2 ${type === 'activity' ? 'bg-primary-100 border-primary-100 text-white' : ''}`,
}}
>
{t('manage.analytics.activities')}
</Button>
<Button
basic
onClick={() => setType('instance')}
className={{
root: `rounded-r border !border-l-0 border-solid px-2 py-0.5 ${type === 'instance' ? 'bg-primary-100 border-primary-100 text-white' : ''}`,
}}
>
{t('manage.analytics.elements')}
</Button>
<div>
<FormLabel
label={t('manage.analytics.dataSource')}
labelType="small"
required={false}
/>
<div className="flex flex-row">
<Button
basic
onClick={() => setType('activity')}
className={{
root: `py-0.25 h-8 rounded-l border !border-r-0 border-solid px-2 ${type === 'activity' ? 'bg-primary-100 border-primary-100 text-white' : ''}`,
}}
>
{t('manage.analytics.activities')}
</Button>
<Button
basic
onClick={() => setType('instance')}
className={{
root: `h-8 rounded-r border !border-l-0 border-solid px-2 py-0.5 ${type === 'instance' ? 'bg-primary-100 border-primary-100 text-white' : ''}`,
}}
>
{t('manage.analytics.elements')}
</Button>
</div>
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,38 +72,40 @@ function ActivityInstanceFeedbacksPlot({
instanceSearch,
})

const ResetButton = () => (
<Button
className={{
root: 'py-0.25 flex h-8 w-max flex-row items-center gap-2 self-end px-2 shadow-none',
}}
disabled={
type === defaultFilters.type &&
activityType === defaultFilters.activityType &&
elementType === defaultFilters.elementType &&
activitySearchTerm === defaultFilters.searchTerm &&
instanceSearchTerm === defaultFilters.searchTerm
}
onClick={() => {
setType(defaultFilters.type)
setActivityType(defaultFilters.activityType)
setElementType(defaultFilters.elementType)
setActivitySearch('')
setInstanceSearch('')
}}
>
<FontAwesomeIcon icon={faX} />
<div>{t('manage.analytics.resetSelectors')}</div>
</Button>
)

return (
<div className="border-uzh-grey-80 rounded-xl border border-solid p-3">
<div className="flex flex-row items-center justify-between">
<div className="mb-2 flex flex-row gap-8">
<H2>{t('manage.analytics.negativeFeedbackOverview')}</H2>
<ActivitiesElementsSwitch type={type} setType={setType} />
</div>
<Button
className={{
root: 'py-0.25 flex h-8 flex-row items-center gap-2 px-2',
}}
disabled={
type === defaultFilters.type &&
activityType === defaultFilters.activityType &&
elementType === defaultFilters.elementType &&
activitySearchTerm === defaultFilters.searchTerm &&
instanceSearchTerm === defaultFilters.searchTerm
}
onClick={() => {
setType(defaultFilters.type)
setActivityType(defaultFilters.activityType)
setElementType(defaultFilters.elementType)
setActivitySearch('')
setInstanceSearch('')
}}
>
<FontAwesomeIcon icon={faX} />
<div>{t('manage.analytics.resetSelectors')}</div>
</Button>
<div className="flex w-full flex-row justify-between gap-8">
<H2>{t('manage.analytics.feedbackOverviewActivityInstances')}</H2>
<ResetButton />
</div>
{type === 'activity' ? (
<div className="flex flex-row items-center gap-8">
<ActivitiesElementsSwitch type={type} setType={setType} />
<ActivityTypeFilter
activityType={activityType}
setActivityType={setActivityType}
Expand All @@ -116,6 +118,7 @@ function ActivityInstanceFeedbacksPlot({
</div>
) : (
<div className="flex flex-row items-center gap-8">
<ActivitiesElementsSwitch type={type} setType={setType} />
<ElementTypeFilter
elementType={elementType}
setElementType={setElementType}
Expand Down Expand Up @@ -145,9 +148,8 @@ function ActivityInstanceFeedbacksPlot({
wrapperStyle={{ top: 0, right: 0 }}
/>
<div className="flex flex-col pt-6">
{entries.length > 0 && (
<div className="max-h-[13rem] overflow-y-scroll">
{entries.map((feedback) => (
{entries.length > 0
? entries.map((feedback) => (
<ElementFeedbackBarChart
key={`upvotes-${feedback.id}`}
title={
Expand All @@ -160,9 +162,8 @@ function ActivityInstanceFeedbacksPlot({
feedback={feedback}
colors={chartColors}
/>
))}
</div>
)}
))
: null}
</div>
</div>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,60 +25,65 @@ function ActivityProgressPlot({
repeated: '#064e3b',
}

const ProgressLegend = () => (
<Legend
payload={[
{
value: t('manage.analytics.started'),
color: chartColors.started,
type: 'rect',
},
{
value: t('manage.analytics.completed'),
color: chartColors.completed,
type: 'rect',
},
{
value: t('manage.analytics.repeated'),
color: chartColors.repeated,
type: 'rect',
},
]}
wrapperStyle={{ bottom: 0, right: 0 }}
/>
)
sjschlapbach marked this conversation as resolved.
Show resolved Hide resolved

return (
<div className="border-uzh-grey-80 rounded-xl border border-solid p-3">
<div className="relative">
<H2>{t('manage.analytics.asynchronousActivityProgress')}</H2>
<Legend
payload={[
{
value: t('manage.analytics.started'),
color: chartColors.started,
type: 'rect',
},
{
value: t('manage.analytics.completed'),
color: chartColors.completed,
type: 'rect',
},
{
value: t('manage.analytics.repeated'),
color: chartColors.repeated,
type: 'rect',
},
]}
wrapperStyle={{ bottom: 0, right: 0 }}
/>
</div>
<H2>{t('manage.analytics.asynchronousActivityProgress')}</H2>
<div className="flex flex-col gap-6">
{pqProgresses.length > 0 && (
<div>
<H4>{t('shared.generic.practiceQuizzes')}</H4>
<div className="max-h-[13rem] overflow-y-scroll">
{pqProgresses.map((progress, idx) => (
<StackedProgress
key={`activity-progress-pq-${idx}`}
progress={progress}
participants={participants}
colors={chartColors}
/>
))}
<div className="relative flex flex-row">
<H4>{t('shared.generic.practiceQuizzes')}</H4>
<ProgressLegend />
</div>
{pqProgresses.map((progress, idx) => (
<StackedProgress
key={`activity-progress-pq-${idx}`}
progress={progress}
participants={participants}
colors={chartColors}
showScale={idx === pqProgresses.length - 1}
/>
))}
</div>
)}
{mlProgresses.length > 0 && (
<div>
<H4>{t('shared.generic.microlearnings')}</H4>
<div className="max-h-[13rem] overflow-y-scroll">
{mlProgresses.map((progress, idx) => (
<StackedProgress
key={`activity-progress-ml-${idx}`}
progress={progress}
participants={participants}
colors={chartColors}
/>
))}
<div className="relative flex flex-row">
<H4>{t('shared.generic.microlearnings')}</H4>
<ProgressLegend />
</div>
{mlProgresses.map((progress, idx) => (
<StackedProgress
key={`activity-progress-ml-${idx}`}
progress={progress}
participants={participants}
colors={chartColors}
showScale={idx === mlProgresses.length - 1}
/>
))}
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,38 +71,42 @@ function PerformanceRates({
attemptsType
)

const ResetButton = () => (
<Button
className={{
root: 'py-0.25 flex h-8 w-max flex-row items-center gap-2 self-end px-2 shadow-none',
}}
disabled={
type === defaultFilters.type &&
attemptsType === defaultFilters.attemptsType &&
activityType === defaultFilters.activityType &&
elementType === defaultFilters.elementType
}
onClick={() => {
setType(defaultFilters.type)
setAttemptsType(defaultFilters.attemptsType)
setActivityType(defaultFilters.activityType)
setElementType(defaultFilters.elementType)
setActivitySearch('')
setInstanceSearch('')
}}
>
<FontAwesomeIcon icon={faX} />
<div>{t('manage.analytics.resetSelectors')}</div>
</Button>
)

return (
<div className="border-uzh-grey-80 rounded-xl border border-solid p-3">
<div className="flex flex-row items-center justify-between">
<div className="mb-2 flex flex-row gap-8">
<div className="flex w-full flex-row justify-between gap-8">
<H2>{t('manage.analytics.activityElementPerformanceRates')}</H2>
<ActivitiesElementsSwitch type={type} setType={setType} />
<ResetButton />
</div>
<Button
className={{
root: 'py-0.25 flex h-8 flex-row items-center gap-2 px-2',
}}
disabled={
type === defaultFilters.type &&
attemptsType === defaultFilters.attemptsType &&
activityType === defaultFilters.activityType &&
elementType === defaultFilters.elementType
}
onClick={() => {
setType(defaultFilters.type)
setAttemptsType(defaultFilters.attemptsType)
setActivityType(defaultFilters.activityType)
setElementType(defaultFilters.elementType)
setActivitySearch('')
setInstanceSearch('')
}}
>
<FontAwesomeIcon icon={faX} />
<div>{t('manage.analytics.resetSelectors')}</div>
</Button>
</div>
{type === 'activity' ? (
<div className="flex flex-row items-center gap-8">
<div className="mb-3 flex flex-col gap-1 lg:flex-row lg:gap-8">
<ActivitiesElementsSwitch type={type} setType={setType} />
<PerformanceAttemptsFilter
attemptsType={attemptsType}
setAttemptsType={setAttemptsType}
Expand All @@ -118,7 +122,8 @@ function PerformanceRates({
/>
</div>
) : (
<div className="flex flex-row items-center gap-8">
<div className="mb-3 flex flex-col gap-1 lg:flex-row lg:gap-8">
<ActivitiesElementsSwitch type={type} setType={setType} />
<PerformanceAttemptsFilter
attemptsType={attemptsType}
setAttemptsType={setAttemptsType}
Expand All @@ -134,6 +139,7 @@ function PerformanceRates({
/>
</div>
)}

{entries.length > 0 ? (
<div className="relative">
<Legend
Expand All @@ -157,18 +163,16 @@ function PerformanceRates({
wrapperStyle={{ top: 0, right: 0 }}
/>
<div className="flex flex-col pt-6">
{entries.length > 0 && (
<div className="max-h-[13rem] overflow-y-scroll">
{entries.map((progress) => (
{entries.length > 0
? entries.map((progress) => (
<PerformanceRatesBarChart
key={`performance-rates-${progress.id}`}
title={progress.name}
rates={progress}
colors={chartColors}
/>
))}
</div>
)}
))
: null}
sjschlapbach marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>
) : (
Expand Down
Loading
Loading