OpptyCloseTimerCmp:

<aura:component controller="OpptyCloseTimerCntrl" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:attribute name="second" type="string"/>
<aura:attribute name="minute" type="string"/>
<aura:attribute name="hour" type="string"/>
<aura:attribute name="day" type="string"/>
<aura:attribute name="msg" type="String"/>
<aura:attribute name="isValid" type="Boolean" default="false"/>
<div class="slds">
<div class="slds-page-header">
<lightning:icon iconName="utility:clock" alternativeText="Countdown" size="small"/>
&nbsp;<b>OPPORTUNITY CLOSE COUNTDOWN</b>
</div>
<aura:if isTrue="{!v.isValid}">
<div class="timerHolder" >
<br/>
<span class="slds-badge">Time Remaining To Close This Opportunity</span>
<div class="slds-grid" style="margin-left:5px;">
<div class="slds-col slds-size--3-of-12">
<div id="day_holder">
<center><b>DAYS</b></center>
<div id="daysBox" >{!v.day}</div>
</div>
</div>
<div class="slds-col slds-size--3-of-12">
<div id="hours_holder">
<center><b>HOURS</b></center>
<div id="hoursBox"> {!v.hour}</div>
</div>
</div>
<div class="slds-col slds-size--3-of-12">
<div id="minutes_holder">
<center><b>MIN</b></center>
<div id="minsBox" > {!v.minute} </div>
</div>
</div>
<div class="slds-col slds-size--3-of-12">
<div id="seconds_holder">
<center><b>SEC</b></center>
<div id="secsBox" > {!v.second} </div>
</div>
</div>
</div>
<br/>
</div>
<aura:set attribute="else">
<div id="msg">
{!v.msg}
</div>
</aura:set>
</aura:if>
</div>
</aura:component>

OpptyCloseTimerCmpController:

({
doInit : function(component, event, helper) {
let action = component.get("c.fetchOpptyCloseDate");
action.setParams({
"recId" : component.get("v.recordId")
});
action.setCallback(this,function(response){
let state = response.getState();
if(state == 'SUCCESS'){
var result = response.getReturnValue();
console.log('Result : ' +result);
var oppCloseDt = new Date(result);
var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
var monthName = months[oppCloseDt.getMonth()];
var dateNumber = oppCloseDt.getDate();
var yearNumber = oppCloseDt.getFullYear();
console.log('Month Name: ' +monthName+' Date: '+dateNumber+' Year: '+yearNumber);
var closeDateVar = monthName+' '+dateNumber+' '+yearNumber;
var opptyCloseDate = new Date( closeDateVar+" 00:00:00 ");
var now_date = new Date();
//console.log('Todays date: ' +now_date);
var timeDiff = opptyCloseDate.getTime()- now_date.getTime();
if(timeDiff<=0){
component.set("v.isValid",false);
component.set("v.msg",'Close Date Expired');
}else{
helper.countDownAction(component, event, helper, closeDateVar);
}
}
});
$A.enqueueAction(action);
}
})

OpptyCloseTimerCmpHelper:

({
countDownAction : function(component, event, helper,closeDate) {
var interval = window.setInterval(
$A.getCallback(function() {
var opptyCloseDate = new Date( closeDate+" 00:00:00 ");
var now_date = new Date();
var timeDiff = opptyCloseDate.getTime()- now_date.getTime(); // time difference between opportunity close date and todays date
component.set("v.isValid",true);
var seconds=Math.floor(timeDiff/1000); // seconds
var minutes=Math.floor(seconds/60); //minute
var hours=Math.floor(minutes/60); //hours
var days=Math.floor(hours/24); //days
hours %=24;
minutes %=60;
seconds %=60;
component.set("v.day",days);
component.set("v.hour",hours);
component.set("v.minute",minutes);
component.set("v.second",seconds);
}), 1000);
}
})

OpptyCloseTimerCmpCSS:

.THIS .timerHolder{
background-color:white;
padding:1%;
}
.THIS #msg{
background-color:white;
padding:1%;
}
.THIS .slds-page-header {
border-radius:0px;
}
.THIS #day_holder{
width:70px;
height:57px;
margin-top:10%;
background-color:#4885ed;
color:#CCC;
font-family:Verdana, Geneva, sans-serif;
font-style:normal;
font-size:15px;
border-radius:1px;
color:white;
}
.THIS #day_holder >#daysBox{
width:64px;
height:30px;
background:#000;
text-align:center;
color:#FF3;
font-family:Verdana, Geneva, sans-serif;
font:bold;
font-size:22px;
position:relative;
top:1px;
left:3px;
border-radius:1px;
}
.THIS #hours_holder{
width:70px;
height:57px;
margin-top:10%;
background-color:#db3236;
color:#CCC;
font-family:Verdana, Geneva, sans-serif;
font-style:normal;
font-size:15px;
border-radius:1px;
color:white;
}
.THIS #hours_holder > #hoursBox{
width:64px;
height:30px;
background:#000;
color:#FF3;
font-family:Verdana, Geneva, sans-serif;
font:bold;
font-size:22px;
position:relative;
top:1px;
left:3px;
text-align:center;
border-radius:1px;
}
.THIS #minutes_holder{
width:70px;
height:57px;
margin-top:10%;
background-color:#f4c20d;
color:#CCC;
font-family:Verdana, Geneva, sans-serif;
font-style:normal;
font-size:15px;
border-radius:1px;
color:white;
}
.THIS #minutes_holder >#minsBox{
width:64px;
height:30px;
background:#000;
color:#FF3;
font-family:Verdana, Geneva, sans-serif;
font:bold;
font-size:22px;
position:relative;
top:1px;
left:3px;
text-align:center;
border-radius:1px;
}
.THIS #seconds_holder{
width:70px;
height:57px;
margin-top:10%;
background-color:#3cba54;
color:#CCC;
font-family:Verdana, Geneva, sans-serif;
font-style:normal;
font-size:15px;
border-radius:1px;
color:white;
}
.THIS #seconds_holder >#secsBox{
width:64px;
height:30px;
background:#000;
color:#FF3;
font-family:Verdana, Geneva, sans-serif;
font:bold;
font-size:22px;
position:relative;
top:1px;
left:3px;
text-align:center;
border-radius:1px;
}

OpptyCloseTimerCntrl:

/* Name:OpptyCloseTimerCntrl
* Description: Fetch the close date of opportunity record based record id.
* Created Date: 25/06/2019
* LastModified Date: 25/06/2019
* Created By: Arun Kumar
*/
public class OpptyCloseTimerCntrl {
@AuraEnabled
public static Date fetchOpptyCloseDate(String recId){
Opportunity opp = [select CloseDate from Opportunity where id =: recId];
system.debug('Close Date: ' +opp.CloseDate);
return opp.CloseDate;
}
}

 

Happy coding… 🙂

Thanks

Arun Kumar