Create an animated bar that fills up based on a target value to measure of whatever KPI is relevant for you.
The blog post: https://salesforcepanda.com/animated-kpi-tracker/
The youtube video: https://youtu.be/LpOJ_1Wzzd8
What you need to know:
- The Stars are static ressources
- The bar is animated
- The ‘motivational’ phrases can be switched and are set for every 10% step
- My use case is tracking calls and the target value is a custom field on the user
Static Ressources
Lightning Component
Component
<aura:component controller="TaskController" implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction,lightning:availableForFlowScreens" access="global">
<aura:attribute name="completedTasks" type="Integer" default="0" />
<aura:attribute name="maxValue" type="Decimal" default="0" />
<aura:attribute name="isProgressing" type="Boolean" default="false" />
<aura:attribute name="progress" type="Integer" default="0" />
<aura:attribute name="starsToShow" type="String" default="Stars_0" />
<aura:attribute name="motivationalPhrase" type="String" default="" />
<aura:attribute name="showExtraText" type="String" default="" />
<aura:attribute name="currentUser" type="User"/>
<aura:attribute name="exceededPercentage" type="String" default=""/>
<aura:attribute name="showExceededText" type="String" default="" />
<aura:attribute name="selectedTimeRange" type="String" default="today" />
<force:recordData aura:id="recordLoader"
recordId="{!$SObjectType.CurrentUser.Id}"
fields="Name"
targetFields="{!v.currentUser}"/>
<aura:handler name="init" value="{!this}" action="{!c.init}" />
<div style="background-color: white; padding-bottom: 4rem; padding-top: 1rem; padding-left: 1rem; padding-right: 1rem;">
<lightning:buttonIcon
iconName="utility:refresh"
alternativeText="Refresh"
variant="bare"
class="slds-float_right"
onclick="{!c.init}"
/>
<div class="slds-form-element__control slds-grow slds-show_inline-block">
<lightning:select name="selectedTimeRange" label="Date Filter" onchange="{!c.onTimeRangeChange}" >
<option value="today">Today</option>
<option value="thisWeek">This Week</option>
<option value="thisMonth">This Month</option>
</lightning:select>
</div>
<div class="stars-container">
<div class="stars-container">
<aura:if isTrue="{!v.starsToShow == 'Stars_0'}">
<img src="{!$Resource.Stars_0}" alt="Zero Stars" style="width: 25%; height: 100%;" />
</aura:if>
<aura:if isTrue="{!v.starsToShow == 'Stars_1'}">
<img src="{!$Resource.Stars_1}" alt="One Star" style="width: 25%; height: 100%;" />
</aura:if>
<aura:if isTrue="{!v.starsToShow == 'Stars_2'}">
<img src="{!$Resource.Stars_2}" alt="Two Stars" style="width: 25%; height: 100%;" />
</aura:if>
<aura:if isTrue="{!v.starsToShow == 'Stars_3'}">
<img src="{!$Resource.Stars_3}" alt="Three Stars" style="width: 25%; height: 100%;" />
</aura:if>
</div>
</div>
<div class="slds-progress-bar slds-progress-bar_circular" aria-valuemin="0" aria-valuemax="100" aria-valuenow="{!v.progress}">
<div class="slds-progress-bar__value" style="{!'width:' + (v.progress > 100 ? 100 : v.progress) + '%; background-color: #5DFCA5;'}">
</div>
<div class="motivational-text">
<p> {!v.motivationalPhrase}</p>
<aura:if isTrue="{!EMPTY(v.exceededPercentage)}">
<p> {!v.progress}% </p>
</aura:if>
<aura:if isTrue="{!NOT(EMPTY(v.exceededPercentage))}">
{!v.exceededPercentage}%
</aura:if>
</div>
</div>
</div>
</aura:component>
Code language: HTML, XML (xml)
Controller
({
onTimeRangeChange: function(component, event, helper) {
var selectedTimeRange = event.getSource().get("v.value");
component.set('v.selectedTimeRange', selectedTimeRange);
console.log("selectedTimeRange: ", selectedTimeRange);
helper.helperInit(component, event, helper, selectedTimeRange);
},
init: function(component, event, helper) {
var userId = $A.get("$SObjectType.CurrentUser.Id");
var selectedTimeRange = component.get("v.selectedTimeRange");
console.log("selectedTimeRange:", selectedTimeRange);
var action = component.get("c.getUserCallGoal");
action.setParams({
userId: userId,
selectedTimeRange: selectedTimeRange
});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var callGoal = response.getReturnValue();
var currentDate = new Date();
console.log("Call Goal:", callGoal);
component.set("v.maxValue", callGoal); // Set the max value for the progress bar
var action2 = component.get("c.getTasksForUserByTimeRange");
var selectedTimeRange = component.get("v.selectedTimeRange");
action2.setParams({
userId: userId,
selectedTimeRange: selectedTimeRange
});
action2.setCallback(this, function(response2) {
var state2 = response2.getState();
if (state2 === "SUCCESS") {
var tasks = response2.getReturnValue();
var completedTasks = tasks.length;
console.log("Completed Tasks:", completedTasks);
component.set("v.completedTasks", completedTasks); // Set the completed tasks attribute
console.log("callGoal:", callGoal);
// Calculate the completed percentage
var completedPercentage1 = (completedTasks / callGoal) * 100;
var completedPercentage = Math.round(completedPercentage1);
// Initialize a counter for real-time completed tasks count
var completedTasksCounter = completedTasks;
var translations = {
'today': 'today',
'thisWeek': 'this week',
'thisMonth': 'this month'
};
var translatedTimeRange = translations[selectedTimeRange] || selectedTimeRange;
// Check if completedTasks is 0
if (completedTasks === 0) {
// Display the initial motivational message
var initialMotivationalPhrase = "Let's go! You have to make " + " " + callGoal + " calls " + translatedTimeRange +"." ;
component.set('v.motivationalPhrase', initialMotivationalPhrase);
} else {
if (completedTasks > callGoal) {
component.set('v.isProgressing', true);
var targetProgress = completedPercentage; // Calculate the target progress
var increment = 1; // Adjust the increment value as needed
component._interval = setInterval($A.getCallback(function() {
var currentProgress = component.get('v.progress');
if (currentProgress < targetProgress ) {
// Increment progress smoothly
var newProgress = Math.min(currentProgress + increment, targetProgress);
component.set('v.progress', newProgress);
// Calculate the completed percentage
var completedPercentage = (completedTasks / callGoal) * 100;
} else {
clearInterval(component._interval);
component.set('v.isProgressing', false);
// Once the calculations are complete, update the final image
// Update starsToShow attribute based on completedTasksCounter
if (completedTasksCounter < 0.8 * callGoal) {
component.set('v.starsToShow', 'Stars_0');
} else if (completedTasksCounter >= 0.8 * callGoal && completedTasksCounter < 0.9 * callGoal) {
component.set('v.starsToShow', 'Stars_1');
} else if (completedTasksCounter >= 0.9 * callGoal && completedTasksCounter < callGoal) {
component.set('v.starsToShow', 'Stars_2');
} else if (completedTasksCounter >= callGoal) { // Only set three stars if the final progress is reached
component.set('v.starsToShow', 'Stars_3');
}
}
}), 20);
var finalMotivationalPhrase = "Is there an incentive coming up? You have exceeded your goal and achieved " + completedTasks + "/" + callGoal + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', finalMotivationalPhrase);
}
// Automatically start progressing if not all tasks are completed
if (completedTasks <= callGoal ) {
component.set('v.isProgressing', true);
var targetProgress = completedPercentage; // Calculate the target progress
var increment = 1; // Adjust the increment value as needed
component._interval = setInterval($A.getCallback(function() {
var currentProgress = component.get('v.progress');
if (currentProgress < targetProgress ) {
// Increment progress smoothly
var newProgress = Math.min(currentProgress + increment, targetProgress);
component.set('v.progress', newProgress);
// Calculate the completed percentage
var completedPercentage = (completedTasks / callGoal) * 100;
if(completedPercentage < 10) {
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "That's a great start! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 20)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Keep it up! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 30)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You're making progress! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 40)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Stay on it! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 50)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Almost halfway there! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 60)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You're on the right track! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 70)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You're on a roll! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 80)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Awesome job! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 90)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Almost there! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 100)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Your phone is buzzing! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage = 100)
{
console.log("completedPercentage",completedPercentage);
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Give yourself a pat on the back! You have reached your goal and completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You are on fire! You've completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " tasks " + selectedTimeRange;
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
} else {
clearInterval(component._interval);
component.set('v.isProgressing', false);
// Once the calculations are complete, update the final image
// Update starsToShow attribute based on completedTasksCounter
if (completedTasksCounter < 0.8 * callGoal) {
component.set('v.starsToShow', 'Stars_0');
} else if (completedTasksCounter >= 0.8 * callGoal && completedTasksCounter < 0.9 * callGoal) {
component.set('v.starsToShow', 'Stars_1');
} else if (completedTasksCounter >= 0.9 * callGoal && completedTasksCounter < callGoal) {
component.set('v.starsToShow', 'Stars_3');
} else if (completedTasksCounter >= callGoal) { // Only set three stars if the final progress is reached
component.set('v.starsToShow', 'Stars_3');
}
}
}), 20); // Adjust the interval duration for smoother animation
}
}
}
});
$A.enqueueAction(action2);
// helper.checkVerteilungsregelnCallGoals(component, event, helper);
}
});
$A.enqueueAction(action);
}
})
Code language: JavaScript (javascript)
Helper
({
helperInit: function(component, event, helper,selectedTimeRange) {
var userId = $A.get("$SObjectType.CurrentUser.Id");
// Clear previous progress and related attributes
component.set('v.progress', 0);
component.set('v.motivationalPhrase', ''); // Clear motivational message
component.set('v.starsToShow', 'Stars_0'); // Reset stars
console.log("userIdZ:", userId);
console.log("selectedTimeRangeZ:", selectedTimeRange);
var action = component.get("c.getUserCallGoal");
action.setParams({
userId: userId,
selectedTimeRange: selectedTimeRange
});
action.setCallback(this, function(response) {
var state = response.getState();
console.log("state:", state);
if (state === "SUCCESS") {
var callGoal = response.getReturnValue();
var currentDate = new Date();
component.set("v.maxValue", callGoal); // Set the max value for the progress bar
console.log("callGoal helper:", callGoal);
var action2 = component.get("c.getTasksForUserByTimeRange");
action2.setParams({
userId: userId,
selectedTimeRange: selectedTimeRange
});
action2.setCallback(this, function(response2) {
var state2 = response2.getState();
if (state2 === "SUCCESS") {
var tasks = response2.getReturnValue();
var completedTasks = tasks.length;
console.log("callGoal state2:", callGoal);
component.set("v.completedTasks", completedTasks); // Set the completed tasks attribute
console.log('completedTasks helperInit: ', completedTasks);
// Calculate the completed percentage
var completedPercentage1 = (completedTasks / callGoal) * 100;
var completedPercentage = Math.round(completedPercentage1);
if (component._interval) {
clearInterval(component._interval);
}
// Initialize a counter for real-time completed tasks count
var completedTasksCounter = completedTasks;
var translations = {
'today': 'today',
'thisWeek': 'this week',
'thisMonth': 'this month'
};
var translatedTimeRange = translations[selectedTimeRange] || selectedTimeRange;
// Check if completedTasks is 0
if (completedTasks === 0) {
// Display the initial motivational message
var initialMotivationalPhrase = "Let's go! You have to make " + " " + callGoal + " calls " + translatedTimeRange +"." ;
component.set('v.motivationalPhrase', initialMotivationalPhrase);
} else {
if (completedTasks > callGoal) {
component.set('v.isProgressing', true);
var targetProgress = completedPercentage; // Calculate the target progress
var increment = 1; // Adjust the increment value as needed
component._interval = setInterval($A.getCallback(function() {
var currentProgress = component.get('v.progress');
if (currentProgress < targetProgress ) {
// Increment progress smoothly
var newProgress = Math.min(currentProgress + increment, targetProgress);
component.set('v.progress', newProgress);
// Calculate the completed percentage
var completedPercentage = (completedTasks / callGoal) * 100;
} else {
clearInterval(component._interval);
component.set('v.isProgressing', false);
// Once the calculations are complete, update the final image
// Update starsToShow attribute based on completedTasksCounter
if (completedTasksCounter < 0.8 * callGoal) {
component.set('v.starsToShow', 'Stars_0');
} else if (completedTasksCounter >= 0.8 * callGoal && completedTasksCounter < 0.9 * callGoal) {
component.set('v.starsToShow', 'Stars_1');
} else if (completedTasksCounter >= 0.9 * callGoal && completedTasksCounter < callGoal) {
component.set('v.starsToShow', 'Stars_2');
} else if (completedTasksCounter >= callGoal) { // Only set three stars if the final progress is reached
component.set('v.starsToShow', 'Stars_3');
}
}
}), 20);
var finalMotivationalPhrase = "Is there an incentive coming up? You have exceeded your goal and achieved " + completedTasks + "/" + callGoal + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', finalMotivationalPhrase);
}
// Automatically start progressing if not all tasks are completed
if (completedTasks <= callGoal ) {
component.set('v.isProgressing', true);
var targetProgress = completedPercentage; // Calculate the target progress
var increment = 1; // Adjust the increment value as needed
component._interval = setInterval($A.getCallback(function() {
var currentProgress = component.get('v.progress');
if (currentProgress < targetProgress ) {
// Increment progress smoothly
var newProgress = Math.min(currentProgress + increment, targetProgress);
component.set('v.progress', newProgress);
// Calculate the completed percentage
var completedPercentage = (completedTasks / callGoal) * 100;
if(completedPercentage < 10) {
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "That's a great start! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 20)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Keep it up! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 30)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You're making progress! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 40)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Stay on it! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 50)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Almost halfway there! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 60)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You're on the right track! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 70)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You're on a roll! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 80)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Awesome job! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 90)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Almost there! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage < 100)
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Your phone is buzzing! You have completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else if (completedPercentage = 100)
{
console.log("completedPercentage",completedPercentage);
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "Give yourself a pat on the back! You have reached your goal and completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " calls " + translatedTimeRange + ".";
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
else
{
// Update completedTasksCounter and motivationalPhrase
completedTasksCounter = Math.floor((newProgress / 100) * callGoal); // Recalculate based on progress
var updatedMotivationalPhrase = "You are on fire! You've completed " + completedTasksCounter + "/" + component.get('v.maxValue') + " tasks " + selectedTimeRange;
component.set('v.motivationalPhrase', updatedMotivationalPhrase);
}
} else {
clearInterval(component._interval);
component.set('v.isProgressing', false);
// Once the calculations are complete, update the final image
// Update starsToShow attribute based on completedTasksCounter
if (completedTasksCounter < 0.8 * callGoal) {
component.set('v.starsToShow', 'Stars_0');
} else if (completedTasksCounter >= 0.8 * callGoal && completedTasksCounter < 0.9 * callGoal) {
component.set('v.starsToShow', 'Stars_1');
} else if (completedTasksCounter >= 0.9 * callGoal && completedTasksCounter < callGoal) {
component.set('v.starsToShow', 'Stars_2');
} else if (completedTasksCounter >= callGoal) { // Only set three stars if the final progress is reached
component.set('v.starsToShow', 'Stars_3');
}
}
}), 20); // Adjust the interval duration for smoother animation
}
}
}
});
$A.enqueueAction(action2);
}
});
$A.enqueueAction(action);
}
})
Code language: JavaScript (javascript)
Style
.THIS .stars-container {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px; /* Adjust this value as needed */
}
.THIS .motivational-text {
position: relative;
top: 10px; /* Adjust the spacing from the circular progress bar */
text-align: center;
font-size: 16px;
background-color: white;
}
Code language: CSS (css)
Apex Class
public with sharing class TaskController {
/**
* Fetches the call goal for a given user based on the selected time range.
* @param userId The ID of the user.
* @param selectedTimeRange The time range (today, thisWeek, thisMonth).
* @return The call goal as a Decimal value.
*/
@AuraEnabled
public static Decimal getUserCallGoal(Id userId, String selectedTimeRange) {
// Query the User object for the call goal fields.
User userRecord = [
SELECT Daily_KPI_Target__c, Weekly_KPI_Target__c, Monthly_KPI_Target__c
FROM User
WHERE Id = :userId
LIMIT 1
];
// If the user record is not found, return 0 to prevent null reference errors.
if (userRecord == null) {
return 0;
}
// Return the appropriate call goal based on the selected time range.
if (selectedTimeRange == 'today') {
return userRecord.Daily_KPI_Target__c != null ? userRecord.Daily_KPI_Target__c : 0;
} else if (selectedTimeRange == 'thisWeek') {
return userRecord.Weekly_KPI_Target__c != null ? userRecord.Weekly_KPI_Target__c : 0;
} else if (selectedTimeRange == 'thisMonth') {
return userRecord.Monthly_KPI_Target__c != null ? userRecord.Monthly_KPI_Target__c : 0;
}
return 0; // Default return value if the time range is invalid.
}
/**
* Fetches tasks assigned to a user within a specific time range.
* @param userId The ID of the user.
* @param selectedTimeRange The time range (today, thisWeek, thisMonth).
* @return A list of Task records that fall within the specified time range.
*/
@AuraEnabled
public static List<Task> getTasksForUserByTimeRange(Id userId, String selectedTimeRange) {
Date currentDate = Date.today();
Date startDate;
Date endDate;
// Determine the start and end date based on the selected time range.
if (selectedTimeRange == 'thisWeek') {
startDate = currentDate.toStartOfWeek();
endDate = startDate.addDays(6); // Get the last day of the current week.
} else if (selectedTimeRange == 'thisMonth') {
startDate = currentDate.toStartOfMonth();
endDate = startDate.addMonths(1).addDays(-1); // Get the last day of the current month.
} else {
// Default to today's tasks.
startDate = currentDate;
endDate = currentDate;
}
// Query tasks that fall within the specified date range and belong to the user.
return [
SELECT Id
FROM Task
WHERE OwnerId = :userId
AND ActivityDate >= :startDate
AND ActivityDate <= :endDate
];
}
/**
* Fetches all tasks assigned to a list of users for today.
* @param userIds List of User IDs.
* @return A map of User IDs to lists of Task records.
*/
@AuraEnabled
public static Map<Id, List<Task>> getTasksForAllUsersToday(List<Id> userIds) {
Date currentDate = Date.today();
// Query all tasks for the provided user IDs for today.
List<Task> tasks = [
SELECT Id, OwnerId
FROM Task
WHERE OwnerId IN :userIds
AND ActivityDate = :currentDate
];
// Map to store tasks grouped by User ID.
Map<Id, List<Task>> tasksByUserId = new Map<Id, List<Task>>();
// Iterate over retrieved tasks and associate them with their respective users.
for (Task task : tasks) {
if (!tasksByUserId.containsKey(task.OwnerId)) {
tasksByUserId.put(task.OwnerId, new List<Task>());
}
tasksByUserId.get(task.OwnerId).add(task);
}
return tasksByUserId;
}
}
Code language: PHP (php)
Formula to calculate business days:
CASE(
MONTH(TODAY()),
1, 22,
2, IF(
OR(
MOD(YEAR(TODAY()), 4) = 0,
AND(MOD(YEAR(TODAY()), 100) = 0, MOD(YEAR(TODAY()), 400) = 0)
),
21,
20
),
3, 23,
4, 22,
5, 23,
6, 20,
7, 23,
8, 23,
9, 21,
10, 23,
11, 22,
12, 21,
0
)
Code language: PHP (php)
Leave a Reply