Snippets Collections
using UnityEngine;

public class Bow : MonoBehaviour
{
    private Vector2 direction; // جهت چرخش
    private Animator anim; // مرجع انیماتور
    private bool isAttacking = false; // وضعیت حمله
    private Rigidbody2D rb; // مرجع Rigidbody2D
    public float horizontalInput;
    public float moveSpeed = 5f; // سرعت حرکت

    void Start()
    {
        // گرفتن انیماتور و Rigidbody2D از آبجکت
        anim = GetComponent<Animator>();
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // حرکت به چپ و راست
        float horizontalInput = Input.GetAxis("Horizontal");

        // اعمال سرعت به Rigidbody2D
        rb.velocity = new Vector2(horizontalInput * moveSpeed, rb.velocity.y);

        // چرخاندن شخصیت بر اساس جهت حرکت
        if (horizontalInput > 0.01f)
        {
            transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y);
        }
        else if (horizontalInput < -0.01f)
        {
            transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y);
        }

        // فعال کردن انیمیشن دویدن
        anim.SetBool("run", horizontalInput != 0);

        //// وقتی دکمه ماوس فشرده می‌شود
        //if (Input.GetMouseButton(0)) // کلیک چپ نگه داشته شود
        //{
        //    StartAttack();
        //}
        //else // وقتی کلیک رها شود
        //{
        //    StopAttack();
        //}

        //// در صورتی که حمله فعال نباشد، چرخش به سمت ماوس انجام شود
        if (!isAttacking)
        {
            Aim();
        }
    }

    void Aim()
    {
        // محاسبه موقعیت ماوس و کمان
        Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector2 bowPos = transform.position;

        // محاسبه جهت
        direction = mousePos - bowPos;

        // چرخش کمان به سمت ماوس
        transform.right = direction;
    }

    //void StartAttack()
    //{
    //    if (!isAttacking)
    //    {
    //        isAttacking = true;
    //        anim.SetBool("click", true); // انیمیشن Attack
    //    }
    //}

    //void StopAttack()
    //{
    //    if (isAttacking)
    //    {
    //        isAttacking = false;
    //        anim.SetBool("click", false); // بازگشت به انیمیشن Idle
    //    }
    //}
}
import pygame
pygame.init()

win = pygame.display.set_mode((500,480))

pygame.display.set_caption("First Game")

walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
bg = pygame.image.load('bg.jpg')
char = pygame.image.load('standing.png')

clock = pygame.time.Clock()


class player(object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5
        self.isJump = False
        self.left = False
        self.right = False
        self.walkCount = 0
        self.jumpCount = 10
        self.standing = True

    def draw(self, win):
        if self.walkCount + 1 >= 27:
            self.walkCount = 0

        if not(self.standing):
            if self.left:
                win.blit(walkLeft[self.walkCount//3], (self.x,self.y))
                self.walkCount += 1
            elif self.right:
                win.blit(walkRight[self.walkCount//3], (self.x,self.y))
                self.walkCount +=1
        else:
            if self.right:
                win.blit(walkRight[0], (self.x, self.y))
            else:
                win.blit(walkLeft[0], (self.x, self.y))
                


class projectile(object):
    def __init__(self,x,y,radius,color,facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.facing = facing
        self.vel = 8 * facing

    def draw(self,win):
        pygame.draw.circle(win, self.color, (self.x,self.y), self.radius)



def redrawGameWindow():
    win.blit(bg, (0,0))
    man.draw(win)
    for bullet in bullets:
        bullet.draw(win)
    
    pygame.display.update()


#mainloop
man = player(200, 410, 64,64)
bullets = []
run = True
while run:
    clock.tick(27)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        
    for bullet in bullets:
        if bullet.x < 500 and bullet.x > 0:
            bullet.x += bullet.vel
        else:
            bullets.pop(bullets.index(bullet))

    keys = pygame.key.get_pressed()

    if keys[pygame.K_SPACE]:
        if man.left:
            facing = -1
        else:
            facing = 1
            
        if len(bullets) < 5:
            bullets.append(projectile(round(man.x + man.width //2), round(man.y + man.height//2), 6, (0,0,0), facing))

    if keys[pygame.K_LEFT] and man.x > man.vel:
        man.x -= man.vel
        man.left = True
        man.right = False
        man.standing = False
    elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
        man.x += man.vel
        man.right = True
        man.left = False
        man.standing = False
    else:
        man.standing = True
        man.walkCount = 0
        
    if not(man.isJump):
        if keys[pygame.K_UP]:
            man.isJump = True
            man.right = False
            man.left = False
            man.walkCount = 0
    else:
        if man.jumpCount >= -10:
            neg = 1
            if man.jumpCount < 0:
                neg = -1
            man.y -= (man.jumpCount ** 2) * 0.5 * neg
            man.jumpCount -= 1
        else:
            man.isJump = False
            man.jumpCount = 10
            
    redrawGameWindow()

pygame.quit()
// banner 

function banners_post() {
	$labels = array(
		'name'                  => _x( 'Banners', 'Post type general name'),
		'singular_name'         => _x( 'Banner', 'Post type singular name'),
		'menu_name'             => _x( 'Banners', 'Admin Menu text'),
		'name_admin_bar'        => _x( 'Banner', 'Add New on Toolbar'),
		'add_new'               => __( 'Add New'),
		'add_new_item'          => __( 'Add New Banner'),
		'new_item'              => __( 'New Banner'),
		'edit_item'             => __( 'Edit Banner'),
		'view_item'             => __( 'View Banner'),
		'all_items'             => __( 'All Banners'),
		'search_items'          => __( 'Search Banners'),
		'parent_item_colon'     => __( 'Parent Banners:'),
		'not_found'             => __( 'No Banners found.'),
		'not_found_in_trash'    => __( 'No Banners found in Trash.'),
	);

	$args = array(
		'labels'             => $labels,
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'query_var'          => true,
		'rewrite'            => array( 'slug' => 'banner' ),
		'capability_type'    => 'post',
		'has_archive'        => true,
		'hierarchical'       => false,
		'menu_position'      => null,
		'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
	);

	register_post_type( 'banner', $args );
}

add_action( 'init', 'banners_post' );


function banner_loop() {
    $args = array(
        'post_type' => 'banner',
        'posts_per_page' => -1
    );

    $query = new WP_Query( $args );
?>
    <section class="bannerSlider slider">
        <?php
    if ( $query->have_posts() ) {
        
        while ( $query->have_posts() ) {
            $query->the_post();
            ?>
                    
            <div>
                <div class="bannerMain">
                    <div class="bannerContent">
                        <?php the_content(); ?>
<!--                         <h5><//?php the_field('banner_designation'); ?></h5> -->
                    </div>
                    <div class="identity">
						<h2><?php the_title(); ?></h2>
                        <?php the_post_thumbnail('full'); ?>
                    </div>
                </div>
            </div>
                
                
            <?php
        }

        // Reset post data
        wp_reset_postdata();
    }
    ?>
    </section>
    <?php
}
add_shortcode('our-banners','banner_loop');

// banners end



jquery
// Initialize Slick Slider for Banner Slider
jQuery(".bannerSlider").slick({
    slidesToShow: 1,
    slidesToScroll: 1,
    dots: true,
    arrows: false,
    prevArrow: '<button class="slide-arrow prev-arrow"></button>',
    nextArrow: '<button class="slide-arrow next-arrow"></button>',
    autoplay: true,
    autoplaySpeed: 5000,
    pauseOnDotsHover: true,
    adaptiveHeight: true,
});

// Initialize Slick Slider for Lazy Loading
jQuery(".lazy").slick({
    lazyLoad: 'ondemand', // ondemand progressive anticipated
    infinite: true
});

// Add Mouse Wheel Navigation
jQuery('.bannerSlider, .lazy').on('wheel', function (e) {
    e.preventDefault(); // Prevent default scrolling behavior
    if (e.originalEvent.deltaY < 0) {
        // Scroll up
        jQuery(this).slick('slickPrev');
    } else {
        // Scroll down
        jQuery(this).slick('slickNext');
    }
});



csss
.top-head h4.info-box-title {
    font-size: 24px !important;
		    line-height: 44px !important;
}

.top-icon .box-icon-wrapper.box-with-icon {
    margin-top: 34px;
}

.wd-header-nav {
    background: #191919;
		height: 60px;

}

span.nav-link-text {
    color: #fff;
    font-size: 18px;
		padding-top: 20px;
}

.info-img span.wd-btn-text {
    color: #d50404;
}

.info-img-1 .info-box-icon {
    width: 100% !important;
}

/* .info-img-1 img {
    width: 100% !important;
}
 */

.info-img span.wd-btn-text:hover {
    color: #000;
}


.bannerContent a {
    background: #ca0404;
    width: 50%;
    padding: 12px 23px;
    color: #fff;
    font-family: 'Poppins';
    font-weight: 500;
}

.bannerContent a:hover {
    background: #2d2d2d;
}


.info-img .btn.btn-style-link {
    border-bottom: none;
}

.info-img-1 .info-box-content {
    background-color: #fbfbfb;
    top: -15px;
    padding: 20px;
    border: 1px solid #999999;
		height: 176px;
}

.info-img .info-box-content {
    background-color: #fbfbfb;
    top: -15px;
    padding: 20px;
    border: 1px solid #999999;
		height: 176px;
}



.info-img-1 a.btn {
    background-color: #ca0404;
    color: #fff;
}

.btn.btn-color-default:hover {
    color: #fff !important;
}

span.fpara {
    color: #7f7f7f;
}

.copyrights-wrapper.copyrights-two-columns {
    display: none;
}


/* newsletter */
.elementor-field-group.elementor-column.elementor-field-type-submit.elementor-col-20.e-form__buttons {
    display: none;
}
/* newsletter */

/* .bannerContent h2 {
    position: absolute;
    top: 2%;
		left: 50%;
    font-size: 34px;
    color: #fff;
}

.bannerContent p {
    position: absolute;
    top: 12%;
    left: 50%;
    right: 5%;
    color: #fff;
} */

.bannerMain img {
    width: 100%;
}


.bannerContent {
    background: #000000ad !important;
    position: absolute;
    z-index: 999;
    top: 0px;
    bottom: 0px;
    right: 0px;
    margin: auto;
    width: 30%;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 50px;
}

.bannerMain {
    position: relative;
}

.bannerImg {
    position: relative;
    z-index: 0;
}

.bannerContent h2 {
    color: #fff;
    font-size: 30px;
}

.bannerContent p {
    color: #fff;
    font-size: 14px;
}

.bannerSlider {
    position: relative;
}

.bannerSlider ul {
    position: absolute;
    bottom: 0;
    display: flex;
    left: 70%;
    padding: 0;
    margin: 0;
    list-style: none;
    width: 30%;
}

.bannerSlider ul li {
    margin: 0;
    width: 16.6%;
    background: linear-gradient(180deg, #383838, #1b1b1b);
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #1b1b1b;
    border-top: 1px solid #2e2e2e;
    border-bottom: 0;
}

.bannerSlider ul li button {
    background: transparent;
    color: #fff;
    font-size: 18px;
}

.menu li a {
    height: 59px;
    display: flex;
    padding: 0 10px;
    align-items: flex-start;
    position: relative;
    z-index: 1;
}

.menu li {
    height: 59px;
    display: flex;
}

.menu li a:after {
    content: '';
    position: absolute;
    width: 100%;
    height: 0px;
    background: linear-gradient(180deg, #d60404, #940101);
    z-index: -1;
    left: 0;
}

.menu li a:hover:after {
    animation: slide-top 0.2s linear both;
}

.slide-top {
	animation: slide-top 0.5s linear both;
}

@keyframes slide-top {
  0% {
    height: 0;
  }
  100% {
    height: 60px;
  }
}

.wd-prefooter {
    padding: 0px;
}


span.auto-style1 {
    color: #E9322D;
    font-size: 28px;
}

.HVR-CLR a {
    color: #d50404;
		font-weight: 600;
}

.HVR-CLR a:hover {
    color: #000;
    text-decoration: underline;
}


input {
    border-color: #E9322D !important;
    color: #000 !important;
    border-radius: 7px !important;
    padding: 20px 10px !important;
}

textarea#wpforms-364-field_6 {
    border-color: #E9322D !important;
    color: #000 !important;
    border-radius: 7px !important;
}

button#wpforms-submit-364 {
    background-color: #000;
    color: #E9322D;
    border: none;
    border-radius: 6px;
    padding: 13px 40px;
    font-size: 16px;
}

input.s.wd-search-inited {
    border: 1px solid #D7D7D7 !important;
}

button.searchsubmit {
    color: #DE352C !important;
}

input.s {
    border-radius: 0px !important;
    border: none;
}


.chaatRow table th {
    border: 2px dashed #000;
}
.chaatRow table tbody td {
    border: 2px dashed #000;
}

::marker {
    color: #BF2130;
}


h2.head1 {
    text-transform: capitalize;
    margin-left: 22px;
    font-size: 30px;
}

h2.bgClr {
    background-color: #C02130;
    color: #fff;
    padding: 10px 30px;
    margin-left: 27px;
}

.chartRow1 table th {
    border: 2px dashed #000;
}
.chartRow1 table tbody td {
    border: 2px dashed #000;
}

.chartRow1 li {
	border-bottom: 2px dashed   #000;
	padding: 8px;
}

p.flexCon {
    font-size: 12px;
}

p.flexCon1 {
    font-size: 12px;
}

p.flexPrice {
    margin-bottom: 0px;
    margin-top: 36px;
}

.chartRow1 ul {
    margin: 0;
}
.chartRow1 ul li:last-child {
    border: none;
}
p.flexCon {
    padding-left: 50px;
}

.chartData p.flexCon {
    padding-left: 50px;
}
.chartRow1 table tbody .chartData ul li {
    padding-bottom: 0;
}

h3.bgClr {
    background-color: #C02130;
    color: #fff;
    padding: 20px;
    text-align: center;
    font-size: 26px;
}


.chartRow3 li div {
    display: flex;
    justify-content: space-between;
}
.chartRow3 li {
    list-style: none;
    border: none;
    position: relative;
}
.chartRow3 li:after {
    content: '';
    position: absolute;
    height: 1px;
    width: 100%;
    border-top: 2px dashed #000;
    right: 100px;
    top: 0;
    bottom: 0;
    margin: auto;
}
.chartRow3 li div h2 {
    margin: 0;
}

.chartRow3 li:nth-child(1):after {
    width: 69%;
}
.chartRow3 li:nth-child(2):after {
    width: 57%;
}
.chartRow3 li:nth-child(3):after {
    width: 45%;
}
.chartRow3 li:nth-child(4):after {
    width: 24%;
}
.chartRow3 li:nth-child(5):after {
    width: 33%;
}
.chartRow3 li:nth-child(6):after {
    width: 29%;
}
.chartRow3 li:nth-child(7):after {
    width: 30%;
}
.chartRow3 li:nth-child(8):after {
    width: 22%;
}

ul.chartRow3.flexChart li div h2 {
    display: flex;
    flex-direction: column;
}

ul.chartRow3.flexChart li div h2 p {
    font-size: 17px;
}

ul.chartRow3.flexChart li:nth-child(1):after {
    width: 43%;
    top: -20px;
}

ul.chartRow3.flexChart li:nth-child(2):after {
    width: 64%;
    top: -30px;
}

ul.chartRow3.flexChart li:nth-child(3):after {
    top: -10px;
    width: 41%;
}

ul.chartRow3.flexChart li:nth-child(4):after {
    width: 67%;
}

ul.chartRow3.flexChart li:nth-child(5):after {
    width: 47%;
}

ul.chartRow3.flexChart.flexChart1 li:nth-child(1):after {
    width: 67%;
    top: -40px;
}

ul.chartRow3.flexChart.flexChart1 li:nth-child(2):after {
    width: 66%;
    top: -40px;
}

ul.chartRow3.flexChart.flexChart1 li:nth-child(3):after {
    width: 60%;
    top: -42px;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(1):after {
    width: 60%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(2):after {
    width: 60%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(3):after {
    width: 62%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(4):after {
    width: 41%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(5):after {
    width: 43%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart li:nth-child(1):after {
    width: 60%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart li:nth-child(2):after {
    width: 58%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart li:nth-child(3):after {
    width: 50%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart.flexChart1 li:nth-child(1):after {
    width: 50%;
}

ul.chartRow5.chartRow3.flexChart.flexChart1 li:nth-child(2):after {
    width: 55%;
}

ul.chartRow5.chartRow3.flexChart.flexChart1 li:nth-child(3):after {
    width: 57%;
    top: 25px;
}




@isTest
    static void testProcessCasesSuccess() {
        List<RecordType> recordTypes2 = [SELECT Id FROM RecordType WHERE SObjectType = 'Case' AND DeveloperName IN ('Reclamacao', 'ProcessoLogistico')];
        List<Case> cases = [SELECT Id, Status, CreatedDate, RecordTypeId FROM Case WHERE RecordTypeId IN :recordTypes2];
        for(Case c : cases) {
            Test.setCreatedDate(c.Id, DateTime.newInstance(2023,12,12));
            c = [SELECT Id, CreatedDate, RecordType.Name, status, StatusDayCount__c FROM Case WHERE Id = :c.Id];
        }
        
        Test.startTest();
        AutoCloseCases.processCases();
        Test.stopTest();
    }
<?php
//Database credentials
$host = 'localhost';
$port = 3306;
$dbName = 'blog';
$username = 'root';
$password = '';

$dsn = "mysql:host={$host};dbname={$dbName};port={$port};charset=utf8";

try {
    // create PDO instance
    $pdo = new PDO($dsn, $username, $password);

//    set PDO to throw exceptions on error
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//    Fetch as associative array
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

} catch (PDOException $e) {
// if error catch
    echo "Connection Failed {$e->getMessage()}";
}
import java.util.*;

public class Main {

    static class Line {
        int x1, y1, x2, y2;

        public Line(int x1, int y1, int x2, int y2) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
        }
    }

    private static int countCells(Line line, Pair<Integer, Integer> star, boolean split) {
        if (line.x1 == line.x2) {
            if (split) {
                return Math.min(Math.abs(star.second - line.y1), Math.abs(star.second - line.y2)) + 1;
            } else {
                return Math.abs(line.y1 - line.y2) + 1;
            }
        } else {
            if (split) {
                return Math.min(Math.abs(star.first - line.x1), Math.abs(star.first - line.x2)) + 1;
            } else {
                return Math.abs(line.x1 - line.x2) + 1;
            }
        }
    }

    private static boolean intersects(Line a, Line b, Pair<Integer, Integer> intersection) {
        if (a.x1 == a.x2 && b.y1 == b.y2) {
            if (b.x1 <= a.x1 && a.x1 <= b.x2 && a.y1 <= b.y1 && b.y1 <= a.y2) {
                intersection.set(a.x1, b.y1);
                return true;
            }
        }
        if (a.y1 == a.y2 && b.x1 == b.x2) {
            if (a.x1 <= b.x1 && b.x1 <= a.x2 && b.y1 <= a.y1 && a.y1 <= b.y2) {
                intersection.set(b.x1, a.y1);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt();
        List<Line> lines = new ArrayList<>();
        for (int i = 0; i < N; ++i) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            if (x1 > x2 || (x1 == x2 && y1 > y2)) {
                int temp = x1;
                x1 = x2;
                x2 = temp;
                temp = y1;
                y1 = y2;
                y2 = temp;
            }
            lines.add(new Line(x1, y1, x2, y2));
        }

        int K = sc.nextInt();
        Map<Pair<Integer, Integer>, List<Line>> stars = new HashMap<>();

        for (int i = 0; i < N; ++i) {
            for (int j = i + 1; j < N; ++j) {
                Pair<Integer, Integer> intersection = new Pair<>(0, 0);
                if (intersects(lines.get(i), lines.get(j), intersection)) {
                    stars.computeIfAbsent(intersection, k -> new ArrayList<>()).add(lines.get(i));
                    stars.computeIfAbsent(intersection, k -> new ArrayList<>()).add(lines.get(j));
                }
            }
        }

        int totalIntensity = 0;
        for (Map.Entry<Pair<Integer, Integer>, List<Line>> entry : stars.entrySet()) {
            if (entry.getValue().size() / 2 == K) {
                List<Integer> intensities = new ArrayList<>();
                for (Line line : entry.getValue()) {
                    intensities.add(countCells(line, entry.getKey(), true));
                }
                totalIntensity += Collections.min(intensities);
            }
        }

        System.out.println(totalIntensity);
    }

    // Pair class to store x and y coordinates of intersections
    static class Pair<T, U> {
        T first;
        U second;

        public Pair(T first, U second) {
            this.first = first;
            this.second = second;
        }

        public void set(T first, U second) {
            this.first = first;
            this.second = second;
        }
    }
}
import java.util.*;

public class Main {
    
    private static int maxRemovals(String currentString, List<String> substrings, Map<String, Integer> memo) {
        if (memo.containsKey(currentString)) {
            return memo.get(currentString);
        }

        int maxCount = 0;

        for (String substring : substrings) {
            int position = currentString.indexOf(substring);
            if (position != -1) {
                String newString = currentString.substring(0, position) + currentString.substring(position + substring.length());
                maxCount = Math.max(maxCount, 1 + maxRemovals(newString, substrings, memo));
            }
        }

        memo.put(currentString, maxCount);
        return maxCount;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int numSubstrings = sc.nextInt();
        List<String> substrings = new ArrayList<>();

        for (int i = 0; i < numSubstrings; i++) {
            substrings.add(sc.next());
        }

        String mainString = sc.next();
        Map<String, Integer> memo = new HashMap<>();

        System.out.println(maxRemovals(mainString, substrings, memo));
    }
}
import java.util.*;

public class Main {
    private static final int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

    private static boolean isValidMove(int x, int y, int gridSize, char[][] grid) {
        return x >= 0 && x < gridSize && y >= 0 && y < gridSize && grid[x][y] != 'M';
    }

    private static int findMinCost(int gridSize, char[][] grid, int[] startPos, int[] endPos) {
        int[][] minCost = new int[gridSize][gridSize];
        for (int i = 0; i < gridSize; i++) {
            Arrays.fill(minCost[i], Integer.MAX_VALUE);
        }

        Queue<int[]> bfsQueue = new LinkedList<>();
        bfsQueue.add(startPos);
        minCost[startPos[0]][startPos[1]] = 0;

        while (!bfsQueue.isEmpty()) {
            int[] currentPos = bfsQueue.poll();
            int x = currentPos[0];
            int y = currentPos[1];

            for (int[] direction : directions) {
                int nextX = x + direction[0];
                int nextY = y + direction[1];

                if (isValidMove(nextX, nextY, gridSize, grid)) {
                    int moveCost = (grid[x][y] == 'T' && grid[nextX][nextY] == 'T') ? 0 : 1;
                    if (minCost[x][y] + moveCost < minCost[nextX][nextY]) {
                        minCost[nextX][nextY] = minCost[x][y] + moveCost;
                        bfsQueue.add(new int[]{nextX, nextY});
                    }
                }
            }
        }

        return minCost[endPos[0]][endPos[1]];
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int gridSize = sc.nextInt();
        char[][] grid = new char[gridSize][gridSize];
        int[] startPos = new int[2];
        int[] endPos = new int[2];

        for (int i = 0; i < gridSize; i++) {
            for (int j = 0; j < gridSize; j++) {
                grid[i][j] = sc.next().charAt(0);
                if (grid[i][j] == 'S') startPos = new int[]{i, j};
                if (grid[i][j] == 'E') endPos = new int[]{i, j};
            }
        }

        int result = findMinCost(gridSize, grid, startPos, endPos);
        System.out.println(result);
    }
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int productCount = sc.nextInt();
        int[] productIds = new int[productCount];
        int[] productCosts = new int[productCount];

        for (int i = 0; i < productCount; i++) {
            productIds[i] = sc.nextInt();
        }
        for (int i = 0; i < productCount; i++) {
            productCosts[i] = sc.nextInt();
        }

        int totalBudget = sc.nextInt();

        int maxFreeItems = 0, maxFreeWorth = 0;

        for (int i = 0; i < productCount; i++) {
            int currentCost = productCosts[i];
            int maxPurchaseQty = totalBudget / currentCost;

            if (maxPurchaseQty > 0) {
                int freeItems = 0;
                int freeWorth = 0;

                for (int j = 0; j < productCount; j++) {
                    if (i != j && productIds[i] % productIds[j] == 0) {
                        freeItems += maxPurchaseQty;
                        freeWorth += productCosts[j] * maxPurchaseQty;
                    }
                }

                if (freeItems > maxFreeItems || 
                   (freeItems == maxFreeItems && freeWorth > maxFreeWorth)) {
                    maxFreeItems = freeItems;
                    maxFreeWorth = freeWorth;
                }
            }
        }

        System.out.println(maxFreeItems + " " + maxFreeWorth);
    }
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int nodes = sc.nextInt();
        int edges = sc.nextInt();
        List<Set<Integer>> adjacencyList = new ArrayList<>();

        for (int i = 0; i < nodes; i++) {
            adjacencyList.add(new HashSet<>());
        }

        for (int i = 0; i < edges; i++) {
            int node1 = sc.nextInt();
            int node2 = sc.nextInt();
            adjacencyList.get(node1).add(node2);
            adjacencyList.get(node2).add(node1);
        }

        int targetActiveNodes = sc.nextInt();
        boolean[] currentActiveNodes = new boolean[nodes];
        Arrays.fill(currentActiveNodes, true);
        int activeNodeCount = nodes;
        int days = 1;

        while (activeNodeCount < targetActiveNodes) {
            boolean[] nextActiveNodes = new boolean[nodes];
            for (int i = 0; i < nodes; i++) {
                int activeNeighbors = 0;
                for (int neighbor : adjacencyList.get(i)) {
                    if (currentActiveNodes[neighbor]) activeNeighbors++;
                }

                if (currentActiveNodes[i] && activeNeighbors == 3) {
                    nextActiveNodes[i] = true;
                } else if (!currentActiveNodes[i] && activeNeighbors < 3) {
                    nextActiveNodes[i] = true;
                }
            }

            currentActiveNodes = nextActiveNodes;
            activeNodeCount = 0;
            for (boolean isActive : currentActiveNodes) {
                if (isActive) activeNodeCount++;
            }
            days++;
        }

        System.out.println(days);
    }
}
git remote add origin https://github.com/Asadullah109/sigma-togather.git
git branch -M main
git push -u origin main
echo "# sigma-togather" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/Asadullah109/sigma-togather.git
git push -u origin main
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String string = br.readLine();
        int length = string.length();
        String[] input = br.readLine().split(" ");
        int[] values = new int[length];

        for (int i = 0; i < length; i++) {
            values[i] = Integer.parseInt(input[i]);
        }

        int res = 0;
        int lastDigit = string.charAt(0) - '0';
        int previousValue = values[0];

        for (int i = 1; i < length; i++) {
            int currentDigit = string.charAt(i) - '0';
            if (currentDigit == lastDigit) {
                res += Math.min(previousValue, values[i]);
                previousValue = Math.max(previousValue, values[i]);
            } else {
                lastDigit = currentDigit;
                previousValue = values[i];
            }
        }

        System.out.println(res);
    }
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String string = sc.next();
        int length = string.length();
        int res = 0;

        int[] values = new int[length];
        for (int i = 0; i < length; i++) {
            values[i] = sc.nextInt();
        }

        int lastDigit = string.charAt(0) - '0';
        int previousValue = values[0];

        for (int i = 1; i < length; i++) {
            int currentDigit = string.charAt(i) - '0';
            if (currentDigit == lastDigit) {
                res += Math.min(previousValue, values[i]);
                previousValue = Math.max(previousValue, values[i]);
            } else {
                lastDigit = currentDigit;
                previousValue = values[i];
            }
        }

        System.out.println(res);
    }
}
int partition(vector<int>& arr, int low, int high) {
  
    // Choose the pivot
    int pivot = arr[high];
    int i = low - 1;

    // Traverse arr[;ow..high] and move all smaller
    
    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    
    // Move pivot after smaller elements and return its posn
    swap(arr[i + 1], arr[high]);  
    return i + 1;
}

void quickSort(vector<int>& arr, int low, int high) {
  
    if (low < high) {
      
        // pi is the partition return index of pivot
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}
		if(head==NULL || k==1){
            return head;
        }
        ListNode* dummy=new ListNode(0);
         dummy->next=head;
        ListNode *cur=dummy,*pre=dummy, *nex=dummy;
       
        int cnt=0;
        while(cur->next!=NULL){
            cur=cur->next;
            cnt++;
        }
        while(cnt>=k){
            cur=pre->next;
            nex= cur->next;
            for(int i=1;i<k;i++){
                cout<<dummy->next->val;
                cur->next=nex->next;
                nex->next=pre->next;
                pre->next=nex;
                nex=cur->next;
                
            }
            pre=cur;
            cnt-=k;
        }
        return dummy->next;
void heapSort(vector<int>& arr){
    int n = arr.size();

    // Build heap (rearrange vector)
    for (int i = n / 2 - 1; i >= 0; i--)
        heapify(arr, n, i);

    // One by one extract an element from heap
    for (int i = n - 1; i > 0; i--) {

        // Move current root to end
        swap(arr[0], arr[i]);

        // Call max heapify on the reduced heap
        heapify(arr, i, 0);
    }
}
void heapify(vector<int>& arr, int n, int i){

    // Initialize largest as root
    int largest = i;

    // left index = 2*i + 1
    int l = 2 * i + 1;

    // right index = 2*i + 2
    int r = 2 * i + 2;

    // If left child is larger than root
    if (l < n && arr[l] > arr[largest])
        largest = l;

    // If right child is larger than largest so far
    if (r < n && arr[r] > arr[largest])
        largest = r;

    // If largest is not root
    if (largest != i) {
        swap(arr[i], arr[largest]);

        // Recursively heapify the affected sub-tree
        heapify(arr, n, largest);
    }
}
#envelope{
margin: 150px;
position: relative;
width: 280px;
height: 180px;
borer-bottom-lefgt-radius:6px;
borer-bottom-lefgt-radius:6px;
margin-left: auto;
margin-left: auto;
top: 150px;
backgorund-color: #f9c5c8
box-shadow: 0 4px 20px rgba(0,0,0,,0.2)
}
for each  account in Account_Certificate[Status == "Draft"]
	{
		if(counter <= 8000)
		{
			accountId = account.ID;
			reciepents = account.Recipient_Emails.toList();
			for each  rec in reciepents
			{
				sendmail
				[
					from :zoho.adminuserid
					to :rec
					subject :"Account Certificate"
					message :"Account Name: " + account.Account_Name
					Attachments :template:Account_Certificate:Account_Certificate accountId as PDF
				]
				counter = counter + 1;
			}
			account.Status="Sent";
		}
	}
	///////// Accounts Emails ///////
	for each  account in Account_Certificate[Status == "Draft"]
	{
		if(counter <= 8000)
		{
			accountId = account.ID;
			reciepents = account.Recipient_Emails.toList();
			for each  rec in reciepents
			{
				sendmail
				[
					from :zoho.adminuserid
					to :rec
					subject :"Account Certificate"
					message :"Account Name: " + account.Account_Name
					Attachments :template:Account_Certificate:Account_Certificate accountId as PDF   ///// template: <record_template2>: <form_link_name2><record_id_variable2> as <attachment_format> //
				]
				counter = counter + 1;
			}
			account.Status="Sent";
		}
	}
import React, { useRef, useState, useEffect } from 'react'
import { HotTable } from '@handsontable/react'
import 'handsontable/dist/handsontable.full.min.css'
import Handsontable from 'handsontable'
import {
  registerControl,
  RegisterControlProps,
  RegisteredControlProperties,
} from '../hoc/registerControl'
import { CustomContentRenderer } from './utils/customButtonRenderer'
import { hyperformulaInstance, sheetId } from './utils/hyperformulaConfig'
import { reformatDate, reformatCurrency } from './utils/formatters'
import { SpreadsheetProperties } from '@components/features/FormBuilder/FormBuilderFieldProperties/Spreadsheet/types'
import { registerAllCellTypes } from 'handsontable/cellTypes'
import { registerAllPlugins } from 'handsontable/plugins'
import { useFormBuilderWorksheetGrid } from '../../hooks/useFormBuilderWorksheetGrid'
import { createSpreadsheetDefaultValue } from '../../FormBuilderFieldProperties/Spreadsheet/constants'
import { useFormBuilder } from '../../hooks/useFormBuilder'
import { useFormService } from '../../hooks/useFormService'

registerAllCellTypes()
registerAllPlugins()

type Properties = RegisteredControlProperties &
  SpreadsheetProperties & {
    externalVariables?: {
      [key: string]: {
        propertyName?: string
        defaultValue?: number
      }
    }
  }

const SpreadsheetControl: React.FC<RegisterControlProps<Properties>> = (
  props
) => {
  const hotTableRef = useRef<any>(null)
  const containerRef = useRef<HTMLDivElement>(null)

  const { rows = 1, columns = 1 } = props.properties || {}

  const DEFAULT_COLUMN_WIDTH = 100
  const DEFAULT_ROW_HEIGHT = 25

  const defaultMeta = {
    data: createSpreadsheetDefaultValue(rows, columns),
    cellFormats: {} as { [key: string]: 'date' | 'currency' | undefined },
    mergeCellsConfig: [],
    formulas: [],
  }

  const meta = props.properties?.meta || defaultMeta
  const { actions: formBuilderWorksheetActions } = useFormBuilderWorksheetGrid()
  const { actions, data: formBuilderData } = useFormBuilder()
  const { watch } = useFormService()
  const formData = watch()

  if (!actions || !actions.getAllFields) {
  }

  const [data, setData] = useState(
    () => props?.value ?? JSON.parse(JSON.stringify(meta.data))
  )
  const [cellFormats, setCellFormats] = useState(meta.cellFormats)
  const [mergeCellsConfig, setMergeCellsConfig] = useState(
    meta.mergeCellsConfig
  )

  const [count, setCount] = useState(0)

  const [formulas, setFormulas] = useState<
    { row: number; col: number; formula: string }[]
  >(meta.formulas || [])

  useEffect(() => {
    if (props.runtime && props.properties?.meta) {
      const {
        data: metaData,
        formulas: metaFormulas = [],

        mergeCellsConfig: metaMergeCells,
      } = props.properties.meta

      setData(props.value ?? metaData)
      setFormulas(metaFormulas)
      setMergeCellsConfig(metaMergeCells)

      metaFormulas.forEach(({ row, col, formula }) => {
        try {
          hyperformulaInstance.setCellContents({ sheet: sheetId, row, col }, [
            [formula],
          ])
        } catch (error) {}
      })

      hyperformulaInstance.rebuildAndRecalculate()
    }
  }, [props.runtime, props.properties?.meta])

  console.log('Meta:', props)

  // useEffect(() => {
  //   if (
  //     !props.externalVariables ||
  //     Object.keys(props.externalVariables).length === 0
  //   ) {
  //     return
  //   }

  //   const existingExpressions = new Set(
  //     hyperformulaInstance.listNamedExpressions()
  //   )

  //   Object.entries(props.externalVariables).forEach(([key, property]) => {
  //     const typedProperty = property as {
  //       propertyName?: string
  //       defaultValue?: number
  //     }
  //     const variableName = typedProperty.propertyName || key
  //     const value = Number(typedProperty.defaultValue || 0)

  //     if (!existingExpressions.has(variableName)) {
  //       try {
  //         hyperformulaInstance.addNamedExpression(variableName, value, sheetId)
  //         existingExpressions.add(variableName)
  //       } catch (error) {
  //         console.error(
  //           `Failed to add named expression: ${variableName}`,
  //           error
  //         )
  //       }
  //     } else {
  //       try {
  //         hyperformulaInstance.changeNamedExpression(
  //           variableName,
  //           value,
  //           sheetId
  //         )
  //       } catch (error) {
  //         console.error(
  //           `Failed to update named expression: ${variableName}`,
  //           error
  //         )
  //       }
  //     }
  //   })

  //   try {
  //     hyperformulaInstance.rebuildAndRecalculate()
  //     syncSpreadsheetWithEngine()
  //   } catch (error) {
  //     console.error('Error recalculating HyperFormula instance:', error)
  //   }
  // }, [props.externalVariables])
  // console.log('External Variable:', props.externalVariables)

  const syncSpreadsheetWithEngine = () => {
    if (hotTableRef.current?.hotInstance && typeof sheetId === 'number') {
      const updatedData = hyperformulaInstance.getSheetValues(sheetId)
      console.log('UpdatedData:', updatedData)
      try {
        hotTableRef.current.hotInstance.loadData(updatedData)
        updateFieldProperties({ data: updatedData })
      } catch (error) {}
    }
  }

  // useEffect(() => {
  //   if (formBuilderData) {
  //     const existingExpressions = hyperformulaInstance.listNamedExpressions()

  //     Object.entries(formBuilderData).forEach(([key, value]) => {
  //       const numericValue = Number(value) || 0

  //       if (!existingExpressions.includes(key)) {
  //         hyperformulaInstance.addNamedExpression(key, numericValue)
  //       } else {
  //         hyperformulaInstance.changeNamedExpression(key, numericValue)
  //       }
  //     })

  //     try {
  //       hyperformulaInstance.rebuildAndRecalculate()

  //       if (sheetId !== undefined) {
  //         const recalculatedData = hyperformulaInstance.getSheetValues(sheetId)
  //         setData(recalculatedData)
  //         updateFieldProperties({ data: recalculatedData })
  //       } else {
  //       }
  //     } catch (error) {}
  //   }
  // }, [formBuilderData])

  // useEffect(() => {
  //   if (formBuilderData?.fields) {
  //     const existingExpressions = new Set(
  //       hyperformulaInstance.listNamedExpressions()
  //     )

  //     formBuilderData.fields.forEach((field) => {
  //       const propertyName = field.properties?.propertyName
  //       const defaultValue = Number(field.properties?.defaultValue || 0)

  //       if (propertyName && !existingExpressions.has(propertyName)) {
  //         try {
  //           hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
  //           existingExpressions.add(propertyName)
  //         } catch (error) {}
  //       } else if (propertyName) {
  //         try {
  //           hyperformulaInstance.changeNamedExpression(
  //             propertyName,
  //             defaultValue
  //           )
  //         } catch (error) {}
  //       }
  //     })

  //     try {
  //       hyperformulaInstance.rebuildAndRecalculate()
  //     } catch (error) {}
  //   }
  // }, [formBuilderData?.fields])

  // useEffect(() => {
  //   const handler = (changes: any) => {
  //     console.log('changes', changes)
  //     hyperformulaInstance.rebuildAndRecalculate()
  //   }

  //   hyperformulaInstance.on('valuesUpdated', handler)

  //   return () => {
  //     hyperformulaInstance.off('valuesUpdated', handler)
  //   }
  // }, [])

  useEffect(() => {
    if (formData && Object.keys(formData).length > 0) {
      console.log('Form Data:', formData)
      const existingExpressions = hyperformulaInstance.listNamedExpressions()

      Object.entries(formData).forEach(([key, value]) => {
        if (!existingExpressions.includes(`${key}`)) {
          hyperformulaInstance.addNamedExpression(`${key}`, Number(value) || 0)
        } else {
          hyperformulaInstance.changeNamedExpression(
            `${key}`,
            Number(value) || 0
          )
        }
        hyperformulaInstance.getNamedExpressionValue(key)
        console.log(
          `get named ${key}`,
          hyperformulaInstance.getNamedExpressionValue(key)
        )

        // hyperformulaInstance.setCellContents(
        //   { sheet: sheetId, row: 0, col: 0 },
        //   [[Number(value) || 0]]
        // )
      })

      hyperformulaInstance.rebuildAndRecalculate()
      // setCount((prev) => prev + 1)
      try {
        // setTimeout(() => {
        //   hyperformulaInstance.rebuildAndRecalculate()
        // }, 100)
      } catch (error) {}
    }
  }, [formData])

  useEffect(() => {
    const adjustedData = adjustDataDimensions(data, rows, columns)
    if (JSON.stringify(data) !== JSON.stringify(adjustedData)) {
      setData(adjustedData)
    }
  }, [rows, columns])

  const adjustDataDimensions = (
    currentData: any[][],
    rows: number,
    columns: number
  ) => {
    const newData = currentData.map((row) => [...row])
    if (newData.length < rows) {
      for (let i = newData.length; i < rows; i++) {
        newData.push(Array(columns).fill(null))
      }
    } else if (newData.length > rows) {
      newData.length = rows
    }
    newData.forEach((row) => {
      if (row.length < columns) {
        row.push(...Array(columns - row.length).fill(null))
      } else if (row.length > columns) {
        row.length = columns
      }
    })
    return newData
  }

  const handleAfterChange = (changes: any, source: string) => {
    if (!changes || source === 'loadData') return

    const validSheetId = sheetId ?? 0
    const updatedFormulas = [...formulas]

    changes.forEach(([row, col, oldValue, newValue]: any) => {
      if (
        newValue &&
        typeof newValue === 'string' &&
        newValue.startsWith('=')
      ) {
        try {
          updatedFormulas.push({ row, col, formula: newValue })
          setFormulas(updatedFormulas)

          hyperformulaInstance.setCellContents(
            { sheet: validSheetId, row, col },
            [[newValue]]
          )
        } catch (error) {}
      }
    })
    const updatedData = hotTableRef.current?.hotInstance?.getData?.()

    setData(updatedData)

    if (props.onChange) {
      props.onChange(updatedData)
    }
    try {
      hyperformulaInstance.rebuildAndRecalculate()
      // setData(hyperformulaInstance.getSheetValues)
      // console.log(
      //   'Get Sheet Value:',
      //   hyperformulaInstance.getSheetValues(sheetId!)
      // )
    } catch (error) {}
  }

  console.log('hotable', hotTableRef.current?.hotInstance?.getData?.())
  // const handleAfterChange = (changes: any, source: string) => {
  //   if (!changes || source === 'loadData') return

  //   const validSheetId = sheetId ?? 0
  //   const updatedFormulas = [...formulas]

  //   changes.forEach(([row, col, oldValue, newValue]: any) => {
  //     if (
  //       newValue &&
  //       typeof newValue === 'string' &&
  //       newValue.startsWith('=')
  //     ) {
  //       try {
  //         updatedFormulas.push({ row, col, formula: newValue })
  //         setFormulas(updatedFormulas)

  //         // hyperformulaInstance.setCellContents(
  //         //   { sheet: validSheetId, row, col },
  //         //   [[newValue]]
  //         // )
  //       } catch (error) {
  //         console.error('Error setting cell contents:', error)
  //       }
  //     }
  //   })

  //   try {
  //     hyperformulaInstance.rebuildAndRecalculate()

  //     const updatedData = hotTableRef.current?.hotInstance?.getData?.()

  //     setData(updatedData)

  //     if (props.onChange) {
  //       props.onChange(updatedData)
  //     }
  //   } catch (error) {
  //     console.error('Error rebuilding and recalculating formulas:', error)
  //   }
  // }

  console.log('hotable', hotTableRef.current?.hotInstance?.getData?.())

  const handleMergeCells = () => {
    const hotInstance = hotTableRef.current?.hotInstance
    const selected = hotInstance?.getSelected()
    if (selected) {
      const [startRow, startCol, endRow, endCol] = selected[0]
      const newMerge = {
        row: startRow,
        col: startCol,
        rowspan: endRow - startRow + 1,
        colspan: endCol - startCol + 1,
      }

      const updatedMergeCellsConfig = [...mergeCellsConfig, newMerge]
      hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
      setMergeCellsConfig(updatedMergeCellsConfig)

      updateFieldProperties({
        data,
        cellFormats,
        mergeCellsConfig: updatedMergeCellsConfig,
      })
    }
  }

  const handleUnmergeCells = () => {
    const hotInstance = hotTableRef.current?.hotInstance
    const selected = hotInstance?.getSelected()
    if (selected) {
      const [startRow, startCol] = selected[0]
      const mergeCellsPlugin = hotInstance.getPlugin('mergeCells')
      mergeCellsPlugin.unmerge(startRow, startCol)

      const updatedMergeCellsConfig = mergeCellsConfig.filter(
        (cell) => cell.row !== startRow || cell.col !== startCol
      )
      hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
      setMergeCellsConfig(updatedMergeCellsConfig)

      updateFieldProperties({
        data,
        cellFormats,
        mergeCellsConfig: updatedMergeCellsConfig,
      })
    }
  }

  const handleSetAsDate = () => {
    const selected = hotTableRef.current?.hotInstance.getSelected()
    if (selected) {
      const [row, col] = selected[0]
      const newFormats = { ...cellFormats, [`${row}-${col}`]: 'date' as const }
      setCellFormats(newFormats)
      updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
    }
  }

  const handleSetAsCurrency = () => {
    const selected = hotTableRef.current?.hotInstance.getSelected()
    if (selected) {
      const [row, col] = selected[0]
      const newFormats = {
        ...cellFormats,
        [`${row}-${col}`]: 'currency' as const,
      }
      setCellFormats(newFormats)
      updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
    }
  }

  const updateFieldProperties = (updatedMeta: any) => {
    formBuilderWorksheetActions?.setFieldConfigProperty(props.config?.id!, {
      meta: {
        data,
        formulas,
        mergeCellsConfig,
        ...updatedMeta,
      },
    })
  }

  const cellsHandler = (row: number, col: number) => {
    const cellProperties = {} as Handsontable.CellProperties
    cellProperties.width = DEFAULT_COLUMN_WIDTH
    cellProperties.height = DEFAULT_ROW_HEIGHT

    const format = cellFormats?.[`${row}-${col}`]

    if (format === 'date') {
      cellProperties.renderer = (
        instance,
        td,
        row,
        col,
        prop,
        value,
        cellProperties
      ) =>
        CustomContentRenderer(instance, td, row, col, () => {
          const span = document.createElement('span')
          span.innerText = reformatDate(
            instance.getDataAtCell(row, col) as string
          )
          return span
        })
    } else if (format === 'currency') {
      cellProperties.renderer = (
        instance,
        td,
        row,
        col,
        prop,
        value,
        cellProperties
      ) =>
        CustomContentRenderer(instance, td, row, col, () => {
          const span = document.createElement('span')
          span.innerText = reformatCurrency(
            instance.getDataAtCell(row, col) as string
          )
          return span
        })
    }

    return cellProperties
  }

  return (
    <div
      ref={containerRef}
      className="h-[400px] w-1/2 resize-x overflow-auto border md:w-full"
      style={{ minWidth: '50%', maxWidth: '100%', resize: 'horizontal' }}
      onMouseDown={(e) => e.stopPropagation()}
    >
      <HotTable
        id="mySpreadsheet"
        data={data}
        colHeaders={true}
        rowHeaders={true}
        width="100%"
        height="100%"
        selectionMode="multiple"
        copyPaste={true}
        contextMenu={{
          items: {
            row_above: {},
            row_below: {},
            col_left: {},
            col_right: {},
            remove_row: {},
            remove_col: {},
            clear_column: {},
            mergeCells: { name: 'Merge Cells', callback: handleMergeCells },
            unmergeCells: {
              name: 'Unmerge Cells',
              callback: handleUnmergeCells,
            },
            set_as_date: { name: 'Set as Date', callback: handleSetAsDate },
            set_as_currency: {
              name: 'Set as Currency',
              callback: handleSetAsCurrency,
            },
          },
        }}
        ref={hotTableRef}
        afterChange={handleAfterChange}
        persistentState={true}
        licenseKey="non-commercial-and-evaluation"
        manualColumnResize={false}
        manualRowResize={false}
        autoColumnSize={false}
        autoRowSize={false}
        stretchH="all"
        mergeCells={mergeCellsConfig}
        formulas={{ engine: hyperformulaInstance }}
        cells={cellsHandler}
        colWidths={DEFAULT_COLUMN_WIDTH}
        rowHeights={DEFAULT_ROW_HEIGHT}
      />
    </div>
  )
}

export default registerControl<Properties>(SpreadsheetControl, {
  noDisplayLabel: true,
})
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":star: Xero Boost Days- What's on! :star:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Hey Manchester! \n\n We're excited to kickstart another great week in the office with our new Boost Day Program! :zap: \n\nPlease see below for what's on this week! "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-1: Tuesday, 3rd December",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: *Café Partnership*: Café-style beverages with *Ditto Coffee*, located at 61, Oxford Street, M1 6EQ and now also at Union, Albert Square, M2 6LW. (Please show your Xero ID to claim your free coffee)\n:breakfast: *Breakfast*: Provided by *Balance Kitchen* from *8:30AM* in the kitchen area."
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-2: Wednesday, 4th December",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: *Café Partnership*: Café-style beverages with *Ditto Coffee*, located at 61 Oxford Street, M1 6EQ and now also at Union, Albert Square, M2 6LW. (Please bring your Xero ID to claim your free coffee)\n:Lunch-2: *Lunch*: Provided by *Balance Kitchen* from *12:30PM* in the kitchen area.\n:party: *Social Happy Hour Alert!* Join us this Wednesday from 4:00 PM to 6:00 PM for the all new Socials— happy hour vibes, great company, and good times. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Comms will be via this slack channel, get ready to Boost your workdays!\n\nLove,\nWX Team :party-wx:"
			}
		}
	]
selector .jet-hor-timeline-item__card {
  height: 24VH;
  transition: height 0.3s ease-in-out;
}

selector .jet-hor-timeline-item__card img {
  height: 100%;
  width: auto;
  object-fit: cover;
}

/* Mobile responsiveness */

@media screen and (max-width: 767px) {
  selector .jet-hor-timeline-item__card {
    height: auto;
  }
}






selector .jet-hor-timeline-item__card-arrow {
    background-image: url('https://hamentorit.co.il/wp-content/uploads/2024/09/ZyrmvYcqZb.gif');
    background-size: cover;
}!
import socket
# client code to connect with API bridge
HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 56789    # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    #ID,Type,Symbol,OrderType,TrigPrice,Price,Qty,InstrumentName,StrategyTag"
    # Symbol = Symbol | Expiry | Strike | OptionType
    # TrigPrice = TrigPrice | StopLoss | SquareOff | TrailingTicks
    # StrategyTag = StrategyTag | Port

    #s.sendall(b"8,LE,SBIN,M,1,180,1,EQ,STG11")
    #s.sendall(b"8,SE,RELIANCE,L,1,180,1,EQ,STG11")
   # s.sendall(b"8,SE,HDFC,L,1,1200,100,EQ,STG11")
    #s.sendall(b"8,SE,INFY|30MAY2019|130|PE,L,1,2000,50,OPTSTK,STG11")
    s.sendall(b"8,LE,MARUTI,L,1,180,1,EQ,STG11")

    data = s.recv(1024)

print('Received', repr(data))
'post__in' => array(301, 344, 342, 995, 998, 1001, 1000, 999),
'orderby' => 'post__in', 


=======
$arg = array(
		'post_type' => 'team',
		'posts_per_page' => -1,
		'post__in' => array(301, 344, 342, 995, 998, 1001, 1000, 999),
    	'orderby' => 'post__in', 
);
/* eslint-disable no-promise-executor-return */
import dayjs from 'dayjs';
import _ from 'lodash';
import {
  useEffect, useRef, useState,
} from 'react';
import {
  useRecoilValue, useSetRecoilState,
} from 'recoil';
import { t } from 'ttag';
import {
  beatEventCountState,
  rhythmEventCountState,
  specialEventTypesState, updatedAfibAvgHrState, updatedDailyAfibHrSummariesState,
} from '.';
import { clearApolloCache } from '../../../../../Apollo/apolloClient';
import fetchHolterBeatEventsCount from '../../../../../Apollo/Functions/fetchHolterBeatEventsCount';
import fetchHolterEventIndex from '../../../../../Apollo/Functions/fetchHolterEventIndex';
import fetchHolterEvents from '../../../../../Apollo/Functions/fetchHolterEvents';
import fetchHolterEventsDailyCount from '../../../../../Apollo/Functions/fetchHolterEventsDailyCount';
import fetchHolterRhythmEventsCount from '../../../../../Apollo/Functions/fetchHolterRhythmEventsCount';
import handleCheckSavingAiProcess from '../../../../../Apollo/Functions/handleCheckSavingAiProcess';
import { EMITTER_CONSTANTS } from '../../../../../ConstantsV2';
import {
  AI_COMMAND,
  canShowCountBeatEvents, canShowDurationEvents,
  ECG_EVENT_MENU_OPTIONS, EVENT_COUNT_CONVERT, ID_BOOKMARK_TAB, KEY_CANCEL, KEY_RECOIL, STRIP_EVENT_THUMBNAIL_INFO, TYPE_RHYTHM_EVENT_ENUM,
  typesPersistEventV2,
} from '../../../../../ConstantsV2/aiConstants';
import { convertToDayJS } from '../../../../../UtilsV2/aiUtils';
import { useEmitter, useGetRecoilValue } from '../../../../../UtilsV2/customHooks';
import emitter from '../../../../../UtilsV2/eventEmitter';
import { toastrError } from '../../../../../UtilsV2/toastNotification';
import {
  activeTabState,
  beatChangesState,
  dailyCountState,
  ecgDataMapState,
  eventChangesState,
  eventFilterState,
  eventNewsState,
  eventOptionsState,
  eventOthersState,
  groupEventChangesState,
  isActiveTabState,
  isNotReadyAfterSaveState,
  isRenderViewerEcgState,
  originalDailySummariesState,
  pageIndexState,
  profileAfibAvgHrState,
  reloadEcgViewerState,
  reloadHrChartState,
  reportInfoState,
  selectedDateValueState,
  selectedStripState,
} from '../../Recoil';
import { logError } from '../../handler';
import {
  generateFilterSpecialEventType,
  isAppliedFilterEvent,
} from '../handler';
import { clearCachesBeatHourly } from '../../../../../Store/caches';
import { removeSavingData } from '../../BeatHR/helper';
import { beatOptionsState } from '../../BeatHR/recoil';

const RhythmEventsRecoilDataEffect = (props) => {
  const keyRecoil = KEY_RECOIL.TAB_2;
  const activeButton = useRecoilValue(activeTabState(keyRecoil));
  const getActiveButton = useGetRecoilValue(activeTabState(keyRecoil));
  const getSelectedStrip = useGetRecoilValue(selectedStripState(keyRecoil));
  const getPageIndex = useGetRecoilValue(pageIndexState(keyRecoil));
  const setPageIndex = useSetRecoilState(pageIndexState(keyRecoil));
  const getSelectedDateValue = useGetRecoilValue(selectedDateValueState(keyRecoil));
  const getSpecialEventTypes = useGetRecoilValue(specialEventTypesState);
  const getEventFilter = useGetRecoilValue(eventFilterState(keyRecoil));
  const setDailyCount = useSetRecoilState(dailyCountState(keyRecoil));
  const setUpdatedAfibAvgHr = useSetRecoilState(updatedAfibAvgHrState);
  const setUpdatedDailyAfibHrSummaries = useSetRecoilState(updatedDailyAfibHrSummariesState);
  const setEventChanges = useSetRecoilState(eventChangesState(keyRecoil));
  const setBeatChanges = useSetRecoilState(beatChangesState(keyRecoil));
  const setReloadEcgViewer = useSetRecoilState(reloadEcgViewerState(keyRecoil));
  const setReloadHrChart = useSetRecoilState(reloadHrChartState(keyRecoil));
  const setGroupEventChanges = useSetRecoilState(groupEventChangesState(keyRecoil));
  const isActiveTab = useRecoilValue(isActiveTabState(keyRecoil));
  const setIsNotReadyAfterSaveTab1 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_1));
  const setIsNotReadyAfterSaveTab2 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_2));
  const setIsNotReadyAfterSaveTab3 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_3));
  const getHolterRhythmEventsCount = useGetRecoilValue(rhythmEventCountState);
  const getHolterBeatEventsCount = useGetRecoilValue(beatEventCountState);
  const { studyId, profileId, timezoneOffset } = useRecoilValue(reportInfoState);
  const setEcgDataMap = useSetRecoilState(ecgDataMapState);
  const getEcgDataMap = useGetRecoilValue(ecgDataMapState);
  const setOriginalDailySummaries = useSetRecoilState(originalDailySummariesState);
  const setProfileAfibAvgHr = useSetRecoilState(profileAfibAvgHrState);
  const setEventOthers = useSetRecoilState(eventOthersState(keyRecoil));
  const setEventNews = useSetRecoilState(eventNewsState(keyRecoil));
  const setEventOptions = useSetRecoilState(eventOptionsState(keyRecoil));
  const setIsRenderViewerEcg = useSetRecoilState(isRenderViewerEcgState);
  const setHolterRhythmEventsCount = useSetRecoilState(rhythmEventCountState);
  const setHolterBeatEventsCount = useSetRecoilState(beatEventCountState);
  const setSelectedStrip = useSetRecoilState(selectedStripState(keyRecoil));
  const [doneReset, setDoneReset] = useState(false);
  const setBeatOptions = useSetRecoilState(beatOptionsState(keyRecoil));

  const commandPendingQueue = useRef([]);
  const updateDataMessageQueue = useRef([]);
  const promiseUpdateData = useRef([]);
  const promiseUpdateDataType = useRef([]);
  const isExcutedRef = useRef(false);

  const handleFetchStripEvents = async ({ page, additionalFilter = {} }) => {
    try {
      const type = getActiveButton();
      const validatePage = page <= 0 ? 0 : page;
      const filterHolterEvents = {
        studyId,
        profileId,
        types: [type],
        skip: validatePage * STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit,
        ...additionalFilter,
      };
      const promises = [fetchHolterEvents(
        filterHolterEvents,
        STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit,
        true,
        KEY_CANCEL.API_HOLTER_AI,
      )];
      if (!_.isEmpty(additionalFilter)) {
        const holterEventsCountFilter = {
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        };
        promises.push(
          _.find(ECG_EVENT_MENU_OPTIONS, (x) => x.value === type).type === 'beat'
            ? fetchHolterBeatEventsCount(holterEventsCountFilter, true, KEY_CANCEL.API_HOLTER_AI)
            : fetchHolterRhythmEventsCount(holterEventsCountFilter, true, KEY_CANCEL.API_HOLTER_AI),
        );
      }
      const [{ events }, eventsCount] = await Promise.all(promises);
      if (!_.isEmpty(additionalFilter)) {
        return { events, eventsCount };
      }
      return { events, eventsCount: _.find(ECG_EVENT_MENU_OPTIONS, (x) => x.value === type).type === 'beat' ? getHolterBeatEventsCount() : getHolterRhythmEventsCount() };
    } catch (error) {
      return { events: undefined, eventsCount: 0 };
    }
  };

  const handleReloadEventHrChartV2 = async () => {
    try {
      const type = activeButton;
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
      ];
      await Promise.allSettled(promiseArr);
      if (!_.includes(promiseUpdateDataType.current, 'setReloadHrChart')) {
        promiseUpdateDataType.current.push('setReloadHrChart');
        promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
      }
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadEventDataV2 = async (needUpdateAfibArtifact) => {
    try {
      if (isActiveTab) {
        setIsRenderViewerEcg(false);
      }
      const type = activeButton;
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const additionalFilter = generateFilterSpecialEventType(type, getSpecialEventTypes());
      const eventFilter = getEventFilter();
      if (isAppliedFilterEvent(eventFilter, type)) {
        _.assign(additionalFilter, {
          ...(eventFilter.isHideReviewed && { isReviewed: false }),
          ...(eventFilter.isCapture && { isCaptured: true }),
          ...(eventFilter.sortOrder && (canShowCountBeatEvents.includes(type) || canShowDurationEvents.includes(type)) && {
            sortBy: eventFilter.sortBy || 'countBeats',
            sortOrder: eventFilter.sortOrder,
          }),
        });
      }
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
        fetchHolterEventsDailyCount({
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        }, null, false),
      ];
      const selectedStrip = getSelectedStrip();
      if (selectedStrip?.idEvent) {
        const filterHolterEventIndex = {
          studyId,
          profileId,
          types: [type],
          includedEventId: selectedStrip.idEvent,
          ...additionalFilter,
        };
        promiseArr.push(fetchHolterEventIndex(filterHolterEventIndex, false, KEY_CANCEL.API_HOLTER_AI));
      } else {
        promiseArr.push(new Promise((resolve) => resolve(undefined)));
      }
      const [resultHolterEventsPersistAllDay, resultDailyCount, resultEventIndex] = await Promise.allSettled(promiseArr);
      const dailyCount = resultDailyCount?.status === 'rejected' ? undefined : resultDailyCount.value;
      if (resultEventIndex?.status === 'fulfilled') {
        const eventIndex = resultEventIndex.value;
        if (!_.isNil(eventIndex) && eventIndex >= 0) {
          const page = Math.floor(eventIndex / STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit);
          await handleFetchStripEvents({ page, additionalFilter });
          promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
        } else {
          const pageIndex = getPageIndex();
          const { events, eventsCount } = await handleFetchStripEvents({ page: pageIndex.index, additionalFilter });
          if (_.isEmpty(events)) {
            const totalEvent = eventsCount[EVENT_COUNT_CONVERT[getActiveButton()]]?.count || 0;
            const pageTemp = Math.floor(totalEvent / STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit);
            const page = (totalEvent % STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit) === 0 ? pageTemp - 1 : pageTemp;
            promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
          } else {
            promiseUpdateData.current.push(() => setPageIndex({ index: getPageIndex().index }));
          }
        }
      }
      if (needUpdateAfibArtifact) {
        handleReloadEventHrChartV2();
      }
      if (!_.isEmpty(dailyCount)) {
        promiseUpdateData.current.push(() => setDailyCount(dailyCount));
      }
      if (!_.includes(promiseUpdateDataType.current, 'setReloadHrChart')) {
        promiseUpdateDataType.current.push('setReloadHrChart');
        promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
      }
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadEvent = async (msg) => {
    try {
      if (isActiveTab) {
        setIsRenderViewerEcg(false);
      }
      const {
        newEvents, deletedEvents, updatedEvents, deletedEventTypes,
      } = msg;
      const selectedDateValue = getSelectedDateValue();
      const selectedDateString = selectedDateValue ? convertToDayJS(selectedDateValue, timezoneOffset).format('DD-MM-YYYY') : null;
      const types = [TYPE_RHYTHM_EVENT_ENUM.AFIB, TYPE_RHYTHM_EVENT_ENUM.ARTIFACT];
      let needUpdate;
      let needUpdateAfibArtifact; //* Trường hợp sửa artifact hoặc afib xong qua tab event khác save thì hr chart ko update
      if (deletedEventTypes?.length) {
        deletedEventTypes.forEach((type) => {
          if (type === activeButton || type === TYPE_RHYTHM_EVENT_ENUM.TACHY) {
            needUpdate = true;
          } else if (types.includes(type)) {
            needUpdateAfibArtifact = true;
          }
        });
      }
      if (deletedEvents?.length) {
        deletedEvents.forEach((deletedEvent) => {
          if (deletedEvent.type === activeButton || (deletedEvent.type === TYPE_RHYTHM_EVENT_ENUM.TACHY)) {
            needUpdate = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(deletedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (types.includes(deletedEvent.type) && isSameDate) {
              needUpdateAfibArtifact = true;
            }
          }
        });
      }
      if (newEvents?.length) {
        newEvents.forEach((newEvent) => {
          if (newEvent.type === activeButton) {
            needUpdate = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(newEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (types.includes(newEvent.type) && isSameDate) {
              needUpdateAfibArtifact = true;
            }
          }
        });
      }
      if (updatedEvents?.length) {
        updatedEvents.forEach((updatedEvent) => {
          if (updatedEvent.type === activeButton) {
            needUpdate = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(updatedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (types.includes(updatedEvent.type) && isSameDate) {
              needUpdateAfibArtifact = true;
            }
          }
        });
      }
      if (needUpdate) {
        await handleReloadEventDataV2(needUpdateAfibArtifact);
      } else if (needUpdateAfibArtifact || activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
        await handleReloadEventHrChartV2();
      } else if (activeButton === ID_BOOKMARK_TAB) {
        if (!_.includes(promiseUpdateDataType.current, 'setReloadHrChart')) {
          promiseUpdateDataType.current.push('setReloadHrChart');
          promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
        }
      }
      console.log('[rhythmEventsRecoilDataEffect]-RELOAD-EVENT-RHYTHMEVENT', needUpdate, activeButton, needUpdateAfibArtifact);
      if (!_.includes(promiseUpdateDataType.current, 'setReloadEcgViewer')) {
        promiseUpdateDataType.current.push('setReloadEcgViewer');
        promiseUpdateData.current.push(() => setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100)));
      }
      promiseUpdateData.current.push(() => {
        setGroupEventChanges((prev) => {
          if (prev.length === 0) {
            return prev;
          }
          return [];
        });
        let eventChanges = [];
        let eventNews = [];
        let eventOthers = [];

        setEventChanges((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventChanges.push(...filterResult);
          return filterResult;
        });
        setEventOthers((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventOthers.push(...filterResult);
          return filterResult;
        });
        setEventNews((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventNews.push(...filterResult);
          return filterResult;
        });

        // Perform grouping action applicable to undo/redo
        setEventOptions({
          eventNewsState: eventNews,
          eventChangesState: eventChanges,
          eventOthersState: eventOthers,
        });

        eventChanges = [];
        eventNews = [];
        eventOthers = [];
        const selectedStrip = getSelectedStrip();
        if (selectedStrip?.isNew) {
          setSelectedStrip(null);
        }
      });
    } catch (error) {
      logError('Error: ', error);
    }
    return true;
  };

  const handleUpdateBeats = (msg) => {
    const prevEcgDataMap = getEcgDataMap();
    const cloneEcgDataMap = { ...prevEcgDataMap };
    if ((msg.summaries?.length || msg.beatsUpdated?.summaries?.length) && !_.isEmpty(prevEcgDataMap?.data)) {
      _.forEach(msg.summaries || msg.beatsUpdated?.summaries, (summary) => {
        const foundData = _.find(cloneEcgDataMap.data, (x) => x.id === summary.id);
        if (foundData) {
          _.assign(foundData, {
            avgHrs: summary?.avgHrs,
            maxHrs: summary?.maxHrs,
            minHrs: summary?.minHrs,
            beatFinalPath: summary?.beatFinalPath,
            latestBeatPrefix: summary?.latestBeatPrefix,
          });
        }
      });

      const summaryIds = _.map(msg.summaries || msg.beatsUpdated?.summaries, 'id');
      const socketUpdateEcgDataMap = {
        ...cloneEcgDataMap,
        data: _.filter(cloneEcgDataMap.data, (item) => summaryIds.includes(item.id)),
      };
      if (isActiveTab) {
        emitter.emit(EMITTER_CONSTANTS.UPDATE_SOCKET_BEAT_DATA_MAP, socketUpdateEcgDataMap);
      }
    }
    return cloneEcgDataMap;
  };

  const handleReloadBeat = async (msg) => {
    try {
      const cloneEcgDataMap = handleUpdateBeats(msg);
      promiseUpdateData.current.push(() => {
        let beatsChanges = [];

        setBeatChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          const beats = removeSavingData(prev);
          beatsChanges = beats;
          return beats;
        });
        setBeatOptions((prev) => ({ ...prev, beatChangesState: beatsChanges }));

        setEcgDataMap((prev) => {
          if (_.isEqual(prev, cloneEcgDataMap)) {
            return prev;
          }
          return cloneEcgDataMap;
        });
        setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100));
      });
    } catch (error) {
      logError('Failed to reload beat', error);
    }
    return true;
  };

  const fetchEventsCount = async () => {
    try {
      const eventsCountFilter = {
        studyId,
        profileId,
      };
      const promises = [
        fetchHolterBeatEventsCount(eventsCountFilter, false, null, false),
        fetchHolterRhythmEventsCount(eventsCountFilter, false, null, false),
      ];
      const [holterBeatEventsCount, holterRhythmEventsCount] = await Promise.all(promises);
      setHolterBeatEventsCount(holterBeatEventsCount);
      setHolterRhythmEventsCount(holterRhythmEventsCount);
    } catch (error) {
      logError('Failed to fetch holter rhythm events count: ', error);
    }
  };

  const updateEventOutOfPending = _.debounce(async () => {
    await clearApolloCache();
    setIsRenderViewerEcg(false);
    setTimeout(() => {
      setIsRenderViewerEcg(true);
    }, 500);
  }, 2000);

  const batchUpdateData = async () => {
    try {
      await clearApolloCache();
      await clearCachesBeatHourly();
      if (isActiveTab || props.activeTab !== '1') {
        setIsRenderViewerEcg(false);
      }
      const promise = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.EVENT) {
          promise.push(handleReloadEvent(x.msg));
          promise.push(fetchEventsCount());
        }
      });
      const beatPromises = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.BEAT) {
          beatPromises.push(handleReloadBeat(x.msg));
        }
      });
      await Promise.all(beatPromises); // Wait for all beat promises to resolve
      console.log('[rhythmEventsRecoilDataEffect]-COMMANDEXECUTED-1', {
        promise,
        updateDataMessageQueue: updateDataMessageQueue.current,
        promiseUpdateData: promiseUpdateData.current,
      });
      await Promise.all(promise);
      promiseUpdateData.current.forEach((update) => update());
      updateDataMessageQueue.current.length = 0;
    } catch (error) {
      logError('Error: ', error);
    } finally {
      console.log('[rhythmEventsRecoilDataEffect]-COMMANDEXECUTED-2', {
        updateDataMessageQueue: updateDataMessageQueue.current,
        promiseUpdateData: promiseUpdateData.current,
      });
      updateDataMessageQueue.current.length = 0;
      promiseUpdateData.current.length = 0;
      commandPendingQueue.current.length = 0;
      promiseUpdateDataType.current.length = 0;
      emitter.emit(EMITTER_CONSTANTS.RELOAD_EVENT_STRIP);
      if (isActiveTab) {
        setDoneReset(true);
      }
    }
  };

  useEffect(() => {
    if (doneReset) {
      setTimeout(() => {
        emitter.emit(EMITTER_CONSTANTS.AI_LOADING, {
          isLoading: false,
          tab: 'rhythmEvents',
          isExcuted: isExcutedRef.current,
        });
        setDoneReset(false);
        if (isExcutedRef.current) {
          isExcutedRef.current = false;
        }
      }, 2000);
    }
  }, [doneReset]);

  useEmitter(EMITTER_CONSTANTS.EVENTSUPDATED_EVENT, (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.EVENT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        Object.keys(msg).forEach((key) => {
          if (foundMsg.msg[key]) {
            foundMsg.msg[key] = foundMsg.msg[key].concat(msg[key]);
          } else {
            foundMsg.msg[key] = msg[key];
          }
        });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.EVENT,
        msg: _.cloneDeep(msg),
      });
    }
    if (commandPendingQueue.current.length === 0) { // update out of pending command
      updateEventOutOfPending();
    }
  }, [studyId, profileId]);

  useEmitter(EMITTER_CONSTANTS.BEATSUPDATED_EVENT, async (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.BEAT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        _.assign(foundMsg, { msg });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.BEAT,
        msg,
      });
    }
  }, []);

  useEmitter(EMITTER_CONSTANTS.DAILY_SUMMARY_UPDATED, (msg) => {
    setOriginalDailySummaries((prev) => {
      if (msg) {
        const cloneDailySummaries = _.cloneDeep(prev);
        _.forEach(msg, (dailySummary) => {
          const foundDailySummary = _.find(cloneDailySummaries, (x) => x.date === dailySummary.date);
          if (foundDailySummary) {
            _.assign(foundDailySummary, dailySummary);
          }
        });
        return cloneDailySummaries;
      }
      return prev;
    });
  }, []);

  useEmitter(EMITTER_CONSTANTS.AFIB_HR_SUMMARY_UPDATED, (msg) => {
    const { afibAvgHr } = msg;
    setProfileAfibAvgHr(afibAvgHr);
    setUpdatedAfibAvgHr(undefined);
    setUpdatedDailyAfibHrSummaries([]);
  }, []);

  useEmitter(EMITTER_CONSTANTS.AI_PROCESS_SAVED, async (msg) => {
    await batchUpdateData();
    setIsNotReadyAfterSaveTab2(false);
  }, [activeButton, studyId, profileId, isActiveTab, props.activeTab]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_PENDING, (msg) => {
    //* Khi 1 user save, BE gửi command pending về tuỳ theo số lượng api gọi lúc save, push command vào mảng và khi
    // có socket command execute thì remove => khi mảng về 0 thì get hết data nhận đc trong mảng updateDataMessage => update UI
    if (msg.messageId !== profileId) return;
    emitter.emit(EMITTER_CONSTANTS.AI_LOADING, { isLoading: true, tab: 'rhythmEvents' });
    commandPendingQueue.current.push(msg.command);
  }, [profileId]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_EXECUTED, async (msg) => {
    // msg.command: update-events, update-beats, updateHolterHrDailySummary
    // updateHolterProfile, generate-report-comments
    if (msg.messageId !== profileId) return;
    if (msg.command === 'updateHolterProfile' || msg.command === 'generate-report-comments') return;
    console.log('[rhythmEventsRecoilDataEffect]-COMMANDEXECUTED-BEFORE', {
      msg,
      commandPendingQueue: commandPendingQueue.current,
      updateDataMessageQueue: updateDataMessageQueue.current,
    });
    const foundIndexCommand = commandPendingQueue.current.findIndex((command) => command === msg.command);
    if (foundIndexCommand !== -1) {
      commandPendingQueue.current.splice(foundIndexCommand, 1);
    }
    //* Finish all command
    if (commandPendingQueue.current.length === 0) {
      isExcutedRef.current = true;
      if (isActiveTab) {
        if (updateDataMessageQueue.current.length !== 0) {
          //* Announce this tab have data to update
          emitter.emit(EMITTER_CONSTANTS.AI_UPDATE_TAB, '2');
          const { beats, events, strips } = await handleCheckSavingAiProcess({
            studyId,
            profileId,
          });
          if (!beats) {
            setIsNotReadyAfterSaveTab1(true);
          }
          if (!strips) {
            setIsNotReadyAfterSaveTab3(true);
          }
          await batchUpdateData();
        } else {
          setDoneReset(true);
        }
      } else {
        await batchUpdateData();
      }
    }
  }, [activeButton, isActiveTab, studyId, profileId, props.activeTab]);

  return null;
};

export default RhythmEventsRecoilDataEffect;
/* eslint-disable no-promise-executor-return */
import dayjs from 'dayjs';
import _ from 'lodash';
import {
  useEffect,
  useRef,
  useState,
} from 'react';
import {
  useRecoilState,
  useRecoilValue,
  useSetRecoilState,
} from 'recoil';
import { t } from 'ttag';
import {
  beatOptionsState,
  dailySummariesCombineState,
  dataHeatmapChartState,
  dataHeatmapChartStatusState,
  generateDefaultHeatmapState,
  listOriginReviewedCellsState,
  listReviewedCellsState,
  listSelectedCellsState,
  listUnReviewedCellsState,
  resetAppliedBulkChangesState,
  rrHeatMapCellChangesState,
  rrOverviewOriginState,
  rrOverviewState,
  totalStripState,
  updatedDailySummariesState,
} from '.';
import fetchHolterBeatEventsCount from '../../../../../Apollo/Functions/fetchHolterBeatEventsCount';
import fetchHolterEventIndex from '../../../../../Apollo/Functions/fetchHolterEventIndex';
import fetchHolterEvents from '../../../../../Apollo/Functions/fetchHolterEvents';
import fetchHolterEventsDailyCount from '../../../../../Apollo/Functions/fetchHolterEventsDailyCount';
import fetchHolterRhythmEventsCount from '../../../../../Apollo/Functions/fetchHolterRhythmEventsCount';
import fetchHolterRrHeatMapCount from '../../../../../Apollo/Functions/fetchHolterRrHeatMapCount';
import fetchHolterRrHeatMapOverview from '../../../../../Apollo/Functions/fetchHolterRrHeatMapOverview';
import handleCheckSavingAiProcess from '../../../../../Apollo/Functions/handleCheckSavingAiProcess';
import { clearApolloCache } from '../../../../../Apollo/apolloClient';
import { EMITTER_CONSTANTS } from '../../../../../ConstantsV2';
import {
  AI_COMMAND,
  EVENT_COUNT_CONVERT,
  KEY_CANCEL,
  KEY_RECOIL,
  STRIP_AFIB_THUMBNAIL_INFO,
  STRIP_ARTIFACT_THUMBNAIL_INFO,
  TYPE_RHYTHM_EVENT_ENUM,
  typesPersistEventV2,
} from '../../../../../ConstantsV2/aiConstants';
import { resetHistoryStateRecoil } from '../../../../../Store/dbHistoryStateRecoil';
import { getDataStateRecoil } from '../../../../../Store/dbStateRecoil';
import { convertToDayJS } from '../../../../../UtilsV2/aiUtils';
import {
  useEmitter,
  useGetRecoilValue,
} from '../../../../../UtilsV2/customHooks';
import emitter from '../../../../../UtilsV2/eventEmitter';
import { toastrError } from '../../../../../UtilsV2/toastNotification';
import {
  activeTabState,
  beatChangesState,
  dailyArtifactCountState,
  dailyCountState,
  ecgDataMapState,
  eventChangesState,
  eventFilterState,
  eventNewsState,
  eventOptionsState,
  eventOthersState,
  groupEventChangesState,
  isActiveTabState,
  isNotReadyAfterSaveState,
  isRenderViewerEcgState,
  originalDailySummariesState,
  pageIndexState,
  profileAfibAvgHrState,
  reloadEcgViewerState,
  reloadHrChartState,
  reportInfoState,
  selectedDateValueState,
  selectedStripState,
} from '../../Recoil';
import { isAppliedFilterEvent } from '../../RhythmEvents/handler';
import { beatEventCountState, rhythmEventCountState } from '../../RhythmEvents/recoil';
import { logError } from '../../handler';
import { formatDataChart } from '../rrInterval/heatMapChart/handler';
import { DATA_HEATMAP_STATUS } from './model';
import { clearCachesBeatHourly } from '../../../../../Store/caches';
import { removeSavingData } from '../helper';

const BeatHrRecoilDataEffect = () => {
  const keyRecoil = KEY_RECOIL.TAB_1;
  const activeButton = useRecoilValue(activeTabState(keyRecoil));
  const getActiveButton = useGetRecoilValue(activeTabState(keyRecoil));
  const getSelectedStrip = useGetRecoilValue(selectedStripState(keyRecoil));
  const selectedDateValue = useRecoilValue(selectedDateValueState(keyRecoil));
  const getSelectedDateValue = useGetRecoilValue(selectedDateValueState(keyRecoil));
  const setBeatChanges = useSetRecoilState(beatChangesState(keyRecoil));
  const setEventChanges = useSetRecoilState(eventChangesState(keyRecoil));
  const setTotalStrip = useSetRecoilState(totalStripState);
  const setDailyCount = useSetRecoilState(dailyCountState(keyRecoil));
  const setArtifactDailyCount = useSetRecoilState(dailyArtifactCountState(keyRecoil));
  const setDailySummariesCombine = useSetRecoilState(dailySummariesCombineState);
  const setRrOverview = useSetRecoilState(rrOverviewState);
  const getRrOverview = useGetRecoilValue(rrOverviewState);
  const setRrOverviewOrigin = useSetRecoilState(rrOverviewOriginState);
  const getPageIndex = useGetRecoilValue(pageIndexState(keyRecoil));
  const setPageIndex = useSetRecoilState(pageIndexState(keyRecoil));
  const [updatedDailySummaries, setUpdatedDailySummaries] = useRecoilState(updatedDailySummariesState);
  const setReloadEcgViewer = useSetRecoilState(reloadEcgViewerState(keyRecoil));
  const setReloadHrChart = useSetRecoilState(reloadHrChartState(keyRecoil));
  const getDataHeatmapChart = useGetRecoilValue(dataHeatmapChartState);
  const getDataHeatmapChartStatus = useGetRecoilValue(dataHeatmapChartStatusState);
  const getListReviewedCells = useGetRecoilValue(listReviewedCellsState);
  const getListUnReviewedCells = useGetRecoilValue(listUnReviewedCellsState);
  const setListReviewedCells = useSetRecoilState(listReviewedCellsState);
  const setListUnReviewedCells = useSetRecoilState(listUnReviewedCellsState);
  const setDataHeatmapChart = useSetRecoilState(dataHeatmapChartState);
  const setDataHeatmapChartStatus = useSetRecoilState(dataHeatmapChartStatusState);
  const setListOriginReviewedCells = useSetRecoilState(listOriginReviewedCellsState);
  const setGroupEventChanges = useSetRecoilState(groupEventChangesState(keyRecoil));
  const getEventFilter = useGetRecoilValue(eventFilterState(keyRecoil));
  const isActiveTab = useRecoilValue(isActiveTabState(keyRecoil));
  const setIsNotReadyAfterSaveTab1 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_1));
  const setIsNotReadyAfterSaveTab2 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_2));
  const setIsNotReadyAfterSaveTab3 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_3));
  const getHolterRhythmEventsCount = useGetRecoilValue(rhythmEventCountState);
  const getListSelectedCells = useGetRecoilValue(listSelectedCellsState);
  const setListSelectedCells = useSetRecoilState(listSelectedCellsState);
  const setEventOthers = useSetRecoilState(eventOthersState(keyRecoil));
  const setEventNews = useSetRecoilState(eventNewsState(keyRecoil));
  const setEventOptions = useSetRecoilState(eventOptionsState(keyRecoil));
  const setHolterRhythmEventsCount = useSetRecoilState(rhythmEventCountState);
  const setHolterBeatEventsCount = useSetRecoilState(beatEventCountState);
  const setSelectedStrip = useSetRecoilState(selectedStripState(keyRecoil));
  const setIsRenderViewerEcg = useSetRecoilState(isRenderViewerEcgState);
  const setRrHeatMapCellChanges = useSetRecoilState(rrHeatMapCellChangesState);
  const setResetAppliedBulkChanges = useSetRecoilState(resetAppliedBulkChangesState);
  const setBeatOptions = useSetRecoilState(beatOptionsState(keyRecoil));

  const {
    studyId,
    profileId,
    timezoneOffset,
  } = useRecoilValue(reportInfoState);
  const [originalDailySummaries, setOriginalDailySummaries] = useRecoilState(originalDailySummariesState);
  const setEcgDataMap = useSetRecoilState(ecgDataMapState);
  const getEcgDataMap = useGetRecoilValue(ecgDataMapState);
  const setProfileAfibAvgHr = useSetRecoilState(profileAfibAvgHrState);

  const commandPendingQueue = useRef([]);
  const updateDataMessageQueue = useRef([]);
  const promiseUpdateData = useRef([]);
  const isExcutedRef = useRef(false);

  const [doneReset, setDoneReset] = useState(false);
  const [doneSetListOriginReviewedCells, setDoneSetListOriginReviewedCells] = useState(true);

  const formatRrOverview = (rrOverview) => {
    const result = generateDefaultHeatmapState({
      reviewed: 1,
      total: 1,
    });
    _.forEach(rrOverview, (x) => {
      result[x.rrHeatMapType] = x.total === 0 ? {
        reviewed: 1,
        total: 1,
      } : {
        reviewed: x.reviewed,
        total: x.total,
      };
    });
    return result;
  };

  const handleFetchRrOverview = async (isFistFetch = false) => {
    // check data from indexdb, if true, no need to fetch data from server
    const rrOver = await getDataStateRecoil('rrOverviewState');
    if (isFistFetch && rrOver) {
      return {};
    }
    try {
      const rrOverview = await fetchHolterRrHeatMapOverview({
        studyId,
        profileId,
      }, null, false);

      const formattedRrOverview = formatRrOverview(rrOverview);
      setRrOverview(formattedRrOverview);
      setRrOverviewOrigin(formattedRrOverview);
    } catch (error) {
      logError('Failed to fetch rr histogram overview', error);
    }
    return {};
  };

  const handleFetchStripEventsArtifact = async (page) => {
    if (!selectedDateValue) {
      return undefined;
    }
    try {
      const validatePage = page <= 0 ? 0 : page;
      const filterHolterEvents = {
        studyId,
        profileId,
        types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
        startRange: {
          start: selectedDateValue,
          stop: dayjs(selectedDateValue).add(1, 'days').toISOString(),
        },
        skip: validatePage * STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit,
      };
      const { events } = await fetchHolterEvents(
        filterHolterEvents,
        STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit,
        true,
        KEY_CANCEL.API_HOLTER_AI,
      );
      return events;
    } catch (error) {
      return undefined;
    }
  };

  const handleFetchStripEventsAfib = async ({ page, additionalFilter = {} }) => {
    try {
      const type = getActiveButton();
      const validatePage = page <= 0 ? 0 : page;
      const filterHolterEvents = {
        studyId,
        profileId,
        types: [type],
        skip: validatePage * STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit,
        ...additionalFilter,
      };
      const promises = [fetchHolterEvents(
        filterHolterEvents,
        STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit,
        true,
        KEY_CANCEL.API_HOLTER_AI,
      )];
      if (!_.isEmpty(additionalFilter)) {
        const holterEventsCountFilter = {
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        };
        promises.push(fetchHolterRhythmEventsCount(holterEventsCountFilter, true, KEY_CANCEL.API_HOLTER_AI));
      }
      const [{ events }, eventsCount] = await Promise.all(promises);
      if (!_.isEmpty(additionalFilter)) {
        return { events, eventsCount };
      }
      return { events, eventsCount: getHolterRhythmEventsCount() };
    } catch (error) {
      return { events: undefined, eventsCount: 0 };
    }
  };

  const handleReloadAfibV2 = async () => {
    try {
      const type = getActiveButton();
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const additionalFilter = {};
      const eventFilter = getEventFilter();
      if (isAppliedFilterEvent(eventFilter, type)) {
        _.assign(additionalFilter, {
          ...(eventFilter.isHideReviewed && { isReviewed: false }),
          ...(eventFilter.isCapture && { isCaptured: true }),
        });
      }
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
        fetchHolterEventsDailyCount({
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        }, null, false),
      ];
      const selectedStrip = getSelectedStrip();
      if (selectedStrip?.idEvent) {
        const filterHolterEventIndex = {
          studyId,
          profileId,
          types: [type],
          includedEventId: selectedStrip.idEvent,
          ...additionalFilter,
        };
        promiseArr.push(fetchHolterEventIndex(filterHolterEventIndex, false, KEY_CANCEL.API_HOLTER_AI));
      } else {
        promiseArr.push(new Promise((resolve) => resolve(undefined)));
      }
      const [resultHolterEventsPersistAllDay, resultDailyCount, resultEventIndex] = await Promise.allSettled(promiseArr);
      const dailyCount = resultDailyCount?.status === 'rejected' ? undefined : resultDailyCount.value;
      if (resultEventIndex?.status === 'fulfilled') {
        const eventIndex = resultEventIndex.value;
        if (!_.isNil(eventIndex) && eventIndex >= 0) {
          const page = Math.floor(eventIndex / STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit);
          await handleFetchStripEventsAfib({ page, additionalFilter });
          promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
        } else {
          const pageIndex = getPageIndex();
          const { events, eventsCount } = await handleFetchStripEventsAfib({ page: pageIndex.index, additionalFilter });
          if (_.isEmpty(events)) {
            const totalEvent = eventsCount[EVENT_COUNT_CONVERT[getActiveButton()]]?.count || 0;
            const pageTemp = Math.floor(totalEvent / STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit);
            const page = (totalEvent % STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit) === 0 ? pageTemp - 1 : pageTemp;
            promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
          } else {
            promiseUpdateData.current.push(() => setPageIndex({ index: getPageIndex().index }));
          }
        }
      }
      if (!_.isEmpty(dailyCount)) {
        if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
          promiseUpdateData.current.push(() => setArtifactDailyCount(dailyCount));
        } else {
          promiseUpdateData.current.push(() => setDailyCount(dailyCount));
        }
      }
      promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadAfibHrChartV2 = async () => {
    try {
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
      ];
      await Promise.allSettled(promiseArr);
      promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadArtifact = async (reloadAll = false) => {
    try {
      // Thumbnail
      const filterDailyCount = {
        studyId,
        profileId,
        types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
      };
      const promiseArr = [
        fetchHolterEventsDailyCount(filterDailyCount, null, false),
      ];
      const selectedDateValue = getSelectedDateValue();
      if (reloadAll) {
        // Strip event
        const selectedStrip = getSelectedStrip();
        if (selectedStrip?.idEvent && selectedDateValue) {
          const filterHolterEventIndex = {
            studyId,
            profileId,
            types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
            startRange: {
              start: selectedDateValue,
              stop: dayjs(selectedDateValue).add(1, 'days').toISOString(),
            },
            includedEventId: selectedStrip.idEvent,
          };
          promiseArr.push(fetchHolterEventIndex(filterHolterEventIndex, false, KEY_CANCEL.API_HOLTER_AI));
        } else {
          promiseArr.push(new Promise((resolve) => resolve(undefined)));
        }
        if (selectedDateValue) {
          // Hr chart: fetch to cache only
          const filterHolterEvents = {
            studyId,
            profileId,
            types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
            startSearchDate: selectedDateValue,
            stopSearchDate: dayjs(selectedDateValue).add(1, 'days').toISOString(),
          };
          promiseArr.push(fetchHolterEvents(filterHolterEvents, 0, true, KEY_CANCEL.API_HOLTER_AI));
        }
      }
      const [resultDailyCount, resultEventIndex, resultHolterEventsAllDay] = await Promise.allSettled(promiseArr);
      const dailyCount = resultDailyCount?.status === 'rejected' ? undefined : resultDailyCount.value;
      if (resultEventIndex?.status === 'fulfilled' && reloadAll) {
        const eventIndex = resultEventIndex.value;
        if (!_.isNil(eventIndex) && eventIndex >= 0) {
          const page = Math.floor(eventIndex / STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit);
          await handleFetchStripEventsArtifact(page);
          promiseUpdateData.current.push(() => {
            if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
              setPageIndex({ index: page < 0 ? 0 : page });
            }
          });
        } else {
          const pageIndex = getPageIndex();
          const events = await handleFetchStripEventsArtifact(pageIndex.index);
          if (_.isEmpty(events)) {
            const currentSelectedDateValue = getSelectedDateValue();
            const totalEvent = _.find(dailyCount, (x) => x.date === currentSelectedDateValue)?.count || 0;
            const pageTemp = Math.floor(totalEvent / STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit);
            const page = (totalEvent % STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit) === 0 ? pageTemp - 1 : pageTemp;
            promiseUpdateData.current.push(() => {
              if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
                setPageIndex({ index: page < 0 ? 0 : page });
              }
            });
          } else {
            promiseUpdateData.current.push(() => {
              if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
                setPageIndex({ index: getPageIndex().index });
              }
            });
          }
        }
      }
      if (!_.isEmpty(dailyCount)) {
        const currentSelectedDateValue = getSelectedDateValue();
        const foundDailyCount = _.find(dailyCount, (x) => x.date === currentSelectedDateValue)?.count;
        promiseUpdateData.current.push(() => {
          if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
            setTotalStrip(foundDailyCount ?? 0);
            setArtifactDailyCount(dailyCount);
          } else {
            setDailyCount(dailyCount);
          }
        });
      }
      promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Error: ', error);
      toastrError(error.message, t`Error`);
    }
    return true;
  };

  const handleReloadEvent = async (msg) => {
    if (isActiveTab) {
      setIsRenderViewerEcg(false);
    }
    try {
      const {
        newEvents, updatedEvents, deletedEvents, deletedEventTypes,
      } = msg;
      // Reload if user in artifact areas and event updated is in selected date
      const selectedDateValue = getSelectedDateValue();
      const selectedDateString = selectedDateValue ? convertToDayJS(selectedDateValue, timezoneOffset).format('DD-MM-YYYY') : null;
      const types = [TYPE_RHYTHM_EVENT_ENUM.AFIB, TYPE_RHYTHM_EVENT_ENUM.ARTIFACT];
      let needUpdateArtifact;
      let needUpdateAfib;
      if (deletedEventTypes?.length && !(needUpdateArtifact || needUpdateAfib)) {
        deletedEventTypes.forEach((type) => {
          if (types.includes(type) && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else if (type === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT && activeButton === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
            needUpdateArtifact = true;
          }
        });
      }
      if (deletedEvents?.length && !(needUpdateArtifact || needUpdateAfib)) {
        deletedEvents.forEach((deletedEvent) => {
          if (deletedEvent.type === activeButton && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(deletedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (deletedEvent.type === activeButton && isSameDate) {
              needUpdateArtifact = true;
            }
          }
        });
      }
      if (updatedEvents?.length && !(needUpdateArtifact || needUpdateAfib)) {
        updatedEvents.forEach((updatedEvent) => {
          if (updatedEvent.type === activeButton && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(updatedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (updatedEvent.type === activeButton && isSameDate) {
              needUpdateArtifact = true;
            }
          }
        });
      }
      if (newEvents?.length && !(needUpdateArtifact || needUpdateAfib)) {
        newEvents.forEach((newEvent) => {
          if (newEvent.type === activeButton && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(newEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (newEvent.type === activeButton && isSameDate) {
              needUpdateArtifact = true;
            }
          }
        });
      }
      if (needUpdateArtifact) {
        await handleReloadArtifact(true);
      } else if (needUpdateAfib) {
        await handleReloadAfibV2();
      } else if (activeButton === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
        await handleReloadArtifact();
      } else if (activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
        await handleReloadAfibHrChartV2();
      }
      console.log('[beatHrRecoilDataEffect]-RELOAD-EVENT-BEATHR', needUpdateArtifact, activeButton);
      promiseUpdateData.current.push(() => {
        setGroupEventChanges((prev) => {
          if (prev.length === 0) {
            return prev;
          }
          return [];
        });

        let eventChanges = [];
        let eventNews = [];
        let eventOthers = [];

        setEventChanges((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventChanges.push(...filterResult);
          return filterResult;
        });
        setEventOthers((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventOthers.push(...filterResult);
          return filterResult;
        });
        setEventNews((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventNews.push(...filterResult);
          return filterResult;
        });
        setEventOptions({
          eventNewsState: eventNews,
          eventChangesState: eventChanges,
          eventOthersState: eventOthers,
        });
        setTimeout(() => {
          resetHistoryStateRecoil();
        }, 200);
        const selectedStrip = getSelectedStrip();
        if (selectedStrip?.isNew) {
          setSelectedStrip(null);
        }
        eventChanges = [];
        eventNews = [];
        eventOthers = [];
      });
      promiseUpdateData.current.push(() => setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Error: ', error);
    }
  };

  const updateCellsStatus = async (listDataHeatmapChart) => {
    const resultListReviewedCells = {};
    const resultListUnReviewedCells = {};
    const resultListOriginReviewedCells = {};

    const listUnReviewedCells = getListUnReviewedCells();

    const dataHeatmapChart = getDataHeatmapChart();
    const listReviewedCells = getListReviewedCells();

    const listSelectedCells = _.filter(getListSelectedCells(), (x) => !_.isNaN(Number(x.id)));
    const newListSelectedCells = [];
    let isSetListSelectedCells = false;
    const activeButton = getActiveButton();

    _.forEach(listDataHeatmapChart, (newDataHeatmapChart, key) => {
      const {
        listReviewedCells: currentListReviewedCells,
        listOriginReviewedCells,
      } = formatDataChart({
        currentDataHeatmapChart: newDataHeatmapChart,
        type: key,
      });
      resultListOriginReviewedCells[key] = listOriginReviewedCells;
      const oldDataHeatmapChart = dataHeatmapChart[key];

      const oldListReviewedCells = listReviewedCells[key];

      const studyId2 = window.location.pathname.split('/')[2];
      const defaultHeatmapState = JSON.parse(localStorage.getItem(`defaultValueHeatmap-${Number(studyId2)}`));

      if (defaultHeatmapState) {
        const resultRrOverviewCells = getRrOverview();
        defaultHeatmapState[key] = {
          newValue: {
            listReviewedCells: listReviewedCells[key],
            listUnReviewedCells: [],
            listSelectedCells: [],
            activeButton: key,
            markCells: 'initialize',
            resetData: true,
            rrOverview: resultRrOverviewCells,
          },
        };
        localStorage.setItem(`defaultValueHeatmap-${Number(studyId2)}`, JSON.stringify(defaultHeatmapState));
      }

      const newListReviewedCells = [];
      /* Điều kiện của list review mới:
        - Có trong list review hiện tại (list review được update trong thời gian saving) và không bị mất đi trong list data mới
        - Không nằm trong list data hiện tại nhưng có trong list data mới và có cờ isRevewed = true
      */
      let isSetListReviewedCells = false;

      _.forEach(currentListReviewedCells, (cells) => {
        // check trong list review
        const isInListOldReviewed = _.some(oldListReviewedCells, { id: cells.id });
        if (isInListOldReviewed) {
          // Có trong list review hiện tại (list review được update trong thời gian saving) và không bị mất đi trong list data mới
          newListReviewedCells.push(cells);
          return;
        }
        // check trong list data heatmap
        const isInListOldData = _.some(oldDataHeatmapChart, { id: cells.id });
        if (!isInListOldData) {
          // Không nằm trong list data hiện tại nhưng có trong list data mới và có cờ isRevewed = true
          isSetListReviewedCells = true;
          newListReviewedCells.push(cells);
        }
      });

      _.forEach(oldListReviewedCells, (cells) => {
        const isInListNewData = _.some(newDataHeatmapChart, { id: cells.id });

        if (!isInListNewData) {
          isSetListReviewedCells = true;
          return;
        }

        const isInCurrentList = _.some(newListReviewedCells, { id: cells.id });
        if (!isInCurrentList) {
          // Có trong list review hiện tại (list review được update trong thời gian saving) và không bị mất đi trong list data mới
          newListReviewedCells.push(cells);
        }
      });

      if (isSetListReviewedCells) {
        resultListReviewedCells[key] = newListReviewedCells;
      }
      // reset list unreview
      if (listUnReviewedCells[key]?.length > 0) {
        resultListUnReviewedCells[key] = [];
      }

      if (key === activeButton) {
        // Nếu có item không nằm trong list hiện tại (sau khi save bị xoá cell) hoặc nằm trong nhưng value thay đổi thì set reload
        _.forEach(listSelectedCells, (cell) => {
          let newDataValue;
          const isInNewData = _.some(newDataHeatmapChart, (item) => {
            if (item.id === cell.id) {
              newDataValue = item.count;
              return true;
            }
            return false;
          });
          if (isInNewData) {
            const newCell = { ...cell, value: newDataValue };
            if (cell.value !== newDataValue) {
              isSetListSelectedCells = true;
            }
            newListSelectedCells.push(newCell);
            return;
          }
          isSetListSelectedCells = true;
        });
      }
    });

    if (!_.isEmpty(resultListReviewedCells)) {
      setListReviewedCells((prev) => ({
        ...prev,
        ...resultListReviewedCells,
      }));
    }

    if (!_.isEmpty(resultListUnReviewedCells)) {
      setListUnReviewedCells((prev) => ({
        ...prev,
        ...resultListUnReviewedCells,
      }));
    }

    setListOriginReviewedCells(resultListOriginReviewedCells);
    if (isSetListSelectedCells) {
      emitter.emit(EMITTER_CONSTANTS.UPDATE_RELOAD_BEAT, newListSelectedCells);
      setListSelectedCells(newListSelectedCells);
    } else {
      emitter.emit(EMITTER_CONSTANTS.UPDATE_RELOAD_BEAT);
    }
  };

  const fetchDataHeatmapChart = async (key) => {
    try {
      const filter = {
        studyId,
        profileId,
        rrHeatMapType: key,
      };
      const newDataHeatmapChart = await fetchHolterRrHeatMapCount(filter, null, false);
      return {
        [key]: newDataHeatmapChart,
      };
    } catch (error) {
      logError('Failed to fetch rr heatmap data', error);
      toastrError(error.message);
      return {};
    }
  };

  const handleReloadRrHeatMap = async () => {
    await clearApolloCache();
    const promiseArr = [handleFetchRrOverview()];

    _.forEach(getDataHeatmapChartStatus(), (value, key) => {
      if (value === DATA_HEATMAP_STATUS.SUCCESS || value === DATA_HEATMAP_STATUS.EMPTY) {
        promiseArr.push(fetchDataHeatmapChart(key));
      }
    });

    const data = await Promise.all(promiseArr);
    const newDataHeatmapChart = {};
    const newDataHeatMapChartStatus = {};
    _.forEach(data, (value) => {
      if (!_.isEmpty(value)) {
        _.assign(newDataHeatmapChart, value);
      }
    });

    Object.keys(newDataHeatmapChart).forEach((key) => {
      if (_.isEmpty(newDataHeatmapChart[key])) {
        newDataHeatMapChartStatus[key] = DATA_HEATMAP_STATUS.EMPTY;
      } else {
        newDataHeatMapChartStatus[key] = DATA_HEATMAP_STATUS.SUCCESS;
      }
    });
    setDataHeatmapChart((prev) => ({
      ...prev,
      ...newDataHeatmapChart,
    }));
    setDataHeatmapChartStatus((prev) => ({
      ...prev,
      ...newDataHeatMapChartStatus,
    }));
    // use setTimeOut in order to waiting all setState in recoil
    updateCellsStatus(newDataHeatmapChart);

    setTimeout(() => {
      emitter.emit(EMITTER_CONSTANTS.UPDATE_HEATMAP_CHART_DATA);
    }, 0);
  };

  const handleUpdateBeats = (msg) => {
    const prevEcgDataMap = getEcgDataMap();
    const cloneEcgDataMap = { ...prevEcgDataMap };
    if ((msg.summaries?.length || msg.beatsUpdated?.summaries?.length) && !_.isEmpty(prevEcgDataMap?.data)) {
      _.forEach(msg.summaries || msg.beatsUpdated?.summaries, (summary) => {
        const foundData = _.find(cloneEcgDataMap.data, (x) => x.id === summary.id);
        if (foundData) {
          _.assign(foundData, {
            avgHrs: summary?.avgHrs,
            maxHrs: summary?.maxHrs,
            minHrs: summary?.minHrs,
            beatFinalPath: summary?.beatFinalPath,
            latestBeatPrefix: summary?.latestBeatPrefix,
          });
        }
      });
      const summaryIds = _.map(msg.summaries || msg.beatsUpdated?.summaries, 'id');
      const socketUpdateEcgDataMap = {
        ...cloneEcgDataMap,
        data: _.filter(cloneEcgDataMap.data, (item) => summaryIds.includes(item.id)),
      };
      if (isActiveTab) {
        emitter.emit(EMITTER_CONSTANTS.UPDATE_SOCKET_BEAT_DATA_MAP, socketUpdateEcgDataMap);
      }
    }
    return cloneEcgDataMap;
  };

  const handleReloadBeat = async (msg) => {
    try {
      const cloneEcgDataMap = handleUpdateBeats(msg);
      promiseUpdateData.current.push(() => {
        let rrHeatMapCellChanges = [];
        const resetAppliedBulkChanges = [];
        let beatsChanges = [];
        setRrHeatMapCellChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          rrHeatMapCellChanges = removeSavingData(prev);
          return rrHeatMapCellChanges;
        });
        setResetAppliedBulkChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          resetAppliedBulkChanges.push(...removeSavingData(prev));
          return resetAppliedBulkChanges;
        });
        setBeatChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          const beats = removeSavingData(prev);
          beatsChanges = beats;
          return beats;
        });
        setBeatOptions((prev) => ({
          ...prev,
          rrHeatMapCellChangesState: rrHeatMapCellChanges,
          resetAppliedBulkChangesState: resetAppliedBulkChanges,
          beatChangesState: beatsChanges,
        }));
        setEcgDataMap((prev) => {
          if (_.isEqual(prev, cloneEcgDataMap)) {
            return prev;
          }
          return cloneEcgDataMap;
        });
        setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100));
      });
    } catch (error) {
      logError('Failed to reload beat', error);
    }
  };

  const fetchEventsCount = async () => {
    try {
      const eventsCountFilter = {
        studyId,
        profileId,
      };
      const promises = [
        fetchHolterBeatEventsCount(eventsCountFilter, false, null, false),
        fetchHolterRhythmEventsCount(eventsCountFilter, false, null, false),
      ];
      const [holterBeatEventsCount, holterRhythmEventsCount] = await Promise.all(promises);
      setHolterBeatEventsCount(holterBeatEventsCount);
      setHolterRhythmEventsCount(holterRhythmEventsCount);
    } catch (error) {
      logError('Failed to fetch holter rhythm events count: ', error);
    }
  };

  const batchUpdateData = async () => {
    try {
      await clearApolloCache();
      await clearCachesBeatHourly();
      if (isActiveTab) {
        setIsRenderViewerEcg(false);
      }
      const promise = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.EVENT) {
          promise.push(handleReloadEvent(x.msg));
          promise.push(fetchEventsCount());
        }
      });
      const beatPromises = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.BEAT) {
          beatPromises.push(handleReloadBeat(x.msg));
        }
      });
      await Promise.all(beatPromises); // Wait for all beat promises to resolve
      await Promise.all(promise); // Wait for all promises to resolve
      promiseUpdateData.current.forEach((update) => update());
    } catch (error) {
      logError('Error: ', error);
    } finally {
      console.log('[beatHrRecoilDataEffect]-COMMANDEXECUTED-2', {
        updateDataMessageQueue: updateDataMessageQueue.current,
        promiseUpdateData: promiseUpdateData.current,
      });
      updateDataMessageQueue.current.length = 0;
      promiseUpdateData.current.length = 0;
      commandPendingQueue.current.length = 0;
      emitter.emit(EMITTER_CONSTANTS.RELOAD_EVENT_STRIP);
      if (isActiveTab) {
        setDoneReset(true);
      }
    }
  };

  const updateEventOutOfPending = _.debounce(async () => {
    await clearApolloCache();
    setIsRenderViewerEcg(false);
    setTimeout(() => {
      setIsRenderViewerEcg(true);
    }, 500);
  }, 2000);

  useEffect(() => {
    handleFetchRrOverview(true);
  }, []);

  useEffect(() => {
    if (originalDailySummaries?.length) {
      const dailySummariesCombine = [];
      for (let i = 0; i < originalDailySummaries.length; i += 1) {
        dailySummariesCombine.push({
          ...originalDailySummaries[i],
          ...(updatedDailySummaries.find((x) => x.date === originalDailySummaries[i].date)),
        });
      }
      setDailySummariesCombine(dailySummariesCombine);
    }
  }, [originalDailySummaries, updatedDailySummaries]);

  useEffect(() => {
    if (doneReset && doneSetListOriginReviewedCells) {
      setTimeout(() => {
        emitter.emit(EMITTER_CONSTANTS.AI_LOADING, {
          tab: 'beatHr',
          isLoading: false,
          isExcuted: isExcutedRef.current,
        });
        setDoneReset(false);
        if (isExcutedRef.current) {
          isExcutedRef.current = false;
        }
      }, 2000);
    }
  }, [doneReset, doneSetListOriginReviewedCells]);

  useEmitter(EMITTER_CONSTANTS.UPDATE_SET_LIST_ORIGIN_REVIEWED_CELLS_STATUS, (msg) => {
    setDoneSetListOriginReviewedCells(msg);
  }, []);

  useEmitter(EMITTER_CONSTANTS.RR_CELL_REVIEWED, () => {
    handleFetchRrOverview();
  }, []);

  useEmitter(EMITTER_CONSTANTS.RR_HEATMAP_UPDATED, () => {
    handleReloadRrHeatMap();
  }, [
    activeButton,
    studyId,
    profileId,
  ]);

  useEmitter(EMITTER_CONSTANTS.EVENTSUPDATED_EVENT, (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.EVENT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        Object.keys(msg).forEach((key) => {
          if (foundMsg.msg[key]) {
            foundMsg.msg[key] = foundMsg.msg[key].concat(msg[key]);
          } else {
            foundMsg.msg[key] = msg[key];
          }
        });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.EVENT,
        msg: _.cloneDeep(msg),
      });
    }
    if (commandPendingQueue.current.length === 0) { // update out of pending command
      updateEventOutOfPending();
    }
  }, []);

  useEmitter(EMITTER_CONSTANTS.BEATSUPDATED_EVENT, (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.BEAT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        _.assign(foundMsg, { msg });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.BEAT,
        msg,
      });
    }
  }, []);

  useEmitter(EMITTER_CONSTANTS.DAILY_SUMMARY_UPDATED, (msg) => {
    setOriginalDailySummaries((prev) => {
      if (msg) {
        const cloneDailySummaries = _.cloneDeep(prev);
        _.forEach(msg, (dailySummary) => {
          const foundDailySummary = _.find(cloneDailySummaries, (x) => x.date === dailySummary.date);
          if (foundDailySummary) {
            _.assign(foundDailySummary, dailySummary);
          }
        });
        return cloneDailySummaries;
      }
      return prev;
    });
    setUpdatedDailySummaries([]);
  }, []);

  useEmitter(EMITTER_CONSTANTS.AFIB_HR_SUMMARY_UPDATED, (msg) => {
    const { afibAvgHr } = msg;
    setProfileAfibAvgHr(afibAvgHr);
  }, []);

  useEmitter(EMITTER_CONSTANTS.AI_PROCESS_SAVED, async (msg) => {
    await batchUpdateData();
    setIsNotReadyAfterSaveTab1(false);
  }, [selectedDateValue, activeButton, studyId, profileId, isActiveTab]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_PENDING, (msg) => {
    // *: Khi 1 user save, BE gửi command pending về tuỳ theo số lượng api gọi lúc save, push command vào mảng và khi
    // có socket command execute thì remove => khi mảng về 0 thì get hết data nhận đc trong mảng updateDataMessage => update UI
    if (msg.messageId !== profileId) {
      return;
    }

    emitter.emit(EMITTER_CONSTANTS.AI_LOADING, {
      tab: 'beatHr',
      isLoading: true,
    });
    commandPendingQueue.current.push(msg.command);
  }, [profileId]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_EXECUTED, async (msg) => {
    // msg.command: update-events, update-beats, updateHolterHrDailySummary,reviewRrIntervals,get-single-events
    // updateHolterProfile, generate-report-comments
    if (msg.messageId !== profileId) return;
    if (msg.command === 'updateHolterProfile' || msg.command === 'generate-report-comments') return;
    console.log('[beatHrRecoilDataEffect]-COMMANDEXECUTED-BEFORE', {
      msg,
      commandPendingQueue: commandPendingQueue.current,
      updateDataMessageQueue: updateDataMessageQueue.current,
    });
    const foundIndexCommand = commandPendingQueue.current.findIndex((command) => command === msg.command);
    if (foundIndexCommand !== -1) {
      commandPendingQueue.current.splice(foundIndexCommand, 1);
    }
    // *: Finish all command
    if (commandPendingQueue.current.length === 0) {
      isExcutedRef.current = true;
      if (isActiveTab) {
        if (updateDataMessageQueue.current.length !== 0) {
          // *: Announce this tab have data to update
          emitter.emit(EMITTER_CONSTANTS.AI_UPDATE_TAB, '1');
          const { events, strips } = await handleCheckSavingAiProcess({
            studyId,
            profileId,
          });
          if (!events) {
            setIsNotReadyAfterSaveTab2(true);
          }
          if (!strips) {
            setIsNotReadyAfterSaveTab3(true);
          }
          await batchUpdateData();
        } else {
          setDoneReset(true);
        }
      } else {
        await batchUpdateData();
      }
    }
  }, [selectedDateValue, activeButton, isActiveTab, studyId, profileId]);

  return null;
};

export default BeatHrRecoilDataEffect;
/* eslint-disable class-methods-use-this */
/* eslint no-console:0 */
// import logHandler from './logHandler';
import { Auth } from '@aws-amplify/auth';
import _ from 'lodash';
import io from 'socket.io-client';
import { EMITTER_CONSTANTS } from '../ConstantsV2';
import AppConstant from '../ConstantsV2/appFlowActions';
import { logError } from '../LayoutV2/Reports/AiEditReport/handler';
import CONFIG from '../config/config';
import auth from './auth';
import emitter from './eventEmitter';

class SocketClient {
  constructor() {
    this.isConnected = false;
    this.isLazyLoading = false;
    this.rooms = [];
    this.intervalRoom = null;

    this.queueECGEvent = [];
    this.queueNewEvent = [];
    this.queueReportUpdate = [];

    this.roomUsersEvent = [];
    this.timeOutRoomEvent = undefined;
    this.intervalJoinRoomEvent = null;
    this.queueRoomEvent = [];

    this.roomUsersReport = [];
    this.timeOutRoomReport = undefined;
    this.intervalJoinRoomReport = null;
    this.queueRoomReport = [];

    this.timeOutOverviewtUpdate = undefined;
    this.queueOverviewUpdate = [];
  }

  getAuth = async () => {
    const accessToken = auth.isLoginWithMicrosoftAccount()
      ? (await Auth.currentSession()).getAccessToken().getJwtToken()
      : auth.token();
    auth.setOriginalToken(accessToken);
    return {
      accessToken,
    };
  };

  connectToServer = async () => {
    try {
      if (!this.socket) {
        this.socket = io(CONFIG.SOCKET, {
          forceNew: true,
          transports: ['websocket'],
          auth: async cb => cb(await this.getAuth()),
          // Prevent disconnect socket before unload to send close event to server
          closeOnBeforeunload: false,
        });
        this.socket.on('connect', this.connectListener);
      }
    } catch (error) {
      logError('Failed to connect socket: ', error);
      this.disconnectSocket();
    }
  };

  connectListener = () => {
    this.isConnected = true;
    auth.setSocketId(this.socket?.id);
    this.socket.off('reconnect');
    this.socket.on('disconnect', this.disconnectListener);
    // this.socket.on('studyEvent', this.studyEventListener);
    // this.socket.on('deviceEvent', this.deviceEventListener);
    // this.socket.on('lastSync', this.lastSyncListener);
    // this.socket.on('studyUpdated', this.studyUpdatedListener);
    // this.socket.on('studyDeleted', this.studyDeletedListener);
    // this.socket.on('inbox', this.inboxListener);
    this.socket.on('roomUsers', this.roomUsersListener);
    this.socket.on('KickClientsByToken', this.kickClientsByTokenListener);
    this.socket.on('KickClientsByUsername', this.kickClientsByUsernameListener);
    this.socket.on('newSession', this.newSessionListener);
    if (auth.isCallCenter()) {
      // this.socket.on('isPreparingFullData', this.isPreparingFullDataListener);
      // this.socket.on('newEvent', this.newEventListener);
      // this.socket.on('multipleEventsClosed', this.multipleEventsClosedListener);
      // this.socket.on('facilityUpdated', this.facilityUpdatedListener);
      // this.socket.on('bucketChanged', this.bucketChangedListener);
      // this.socket.on('moreStudies', this.moreStudiesListener);

      this.socket.on('eventUpdated', this.eventUpdatedListener);
      this.socket.on('reportUpdated', this.reportUpdatedListener);
      this.socket.on('groupUpdated', this.groupUpdatedListener);
      this.socket.on('profileReady', this.profileReadyListener);
      this.socket.on('beatsUpdated', this.beatsUpdatedListener);
      this.socket.on('eventsUpdated', this.eventsUpdatedListener);
      this.socket.on('dailySummaryUpdated', this.dailySummaryUpdatedListener);
      this.socket.on('afibHrSummaryUpdated', this.afibHrSummaryUpdatedListener);
      this.socket.on('holterProfileUpdated', this.holterProfileUpdatedListener);
      this.socket.on('technicianCommentsUpdated', this.technicianCommentsUpdatedListener);
      this.socket.on('rrCellsReviewed', this.rrCellsReviewedListener);
      this.socket.on('commandProgressUpdated', this.commandProgressUpdatedListener);
      this.socket.on('commandExecuted', this.commandExecutedListener);
      this.socket.on('commandPending', this.commandPendingListener);
      this.socket.on('rrHeatMapUpdated', this.rrHeatMapUpdatedListener);
      this.socket.on('aiProcessSaved', this.aiProcessSavedListener);
      this.socket.on('migrateAiData', this.migrateAiDataListener);
      this.socket.on('reCapturedEvents', this.reCapturedEventsListener);
    }
    //* Test socket
    // setTimeout(() => {
    //   emitter.emit(EMITTER_CONSTANTS.COMMAND_PENDING, {
    //     messageId: '65857578925735af4701e5ad',
    //     command: 'update-beats',
    //   });
    // }, 10000);
    // setTimeout(() => {
    //   emitter.emit(EMITTER_CONSTANTS.COMMAND_EXECUTED, {
    //     messageId: '65857578925735af4701e5ad',
    //     command: 'update-beats',
    //     isSuccess: true,
    //   });
    // }, 11000);
  };

  disconnectListener = (error) => {
    console.log('socket io - on disconnect:', error);

    // emitter.emit(EMITTER_CONSTANTS.LOST_CONNECTION, CONNECTION_TYPE.SOCKET);
    // alert('Sorry for the inconvenience!\nThe system ran into a problem and needs to reload a page.');
    // window.location.reload();

    this.isConnected = false;
    this.socket.io.on('reconnect', this.reconnectListener);

    this.socket.off('connect');
    this.socket.off('disconnect');

    // this.socket.off('studyEvent');
    // this.socket.off('deviceEvent');
    // this.socket.off('lastSync');
    // this.socket.off('studyUpdated');
    // this.socket.off('studyDeleted');
    // this.socket.off('inbox');
    this.socket.off('roomUsers');
    this.socket.off('KickClientsByToken');
    this.socket.off('KickClientsByUsername');
    this.socket.off('newSession');

    if (auth.isCallCenter()) {
      // this.socket.off('isPreparingFullData');
      // this.socket.off('newEvent');
      // this.socket.off('multipleEventsClosed');
      // this.socket.off('facilityUpdated');
      // this.socket.off('bucketChanged');
      // this.socket.off('moreStudies');

      this.socket.off('eventUpdated');
      this.socket.off('reportUpdated');
      this.socket.off('groupUpdated');
      this.socket.off('profileReady');
      this.socket.off('beatsUpdated');
      this.socket.off('eventsUpdated');
      this.socket.off('dailySummaryUpdated');
      this.socket.off('afibHrSummaryUpdated');
      this.socket.off('holterProfileUpdated');
      this.socket.off('technicianCommentsUpdated');
      this.socket.off('rrCellsReviewed');
      this.socket.off('commandProgressUpdated');
      this.socket.off('commandExecuted');
      this.socket.off('commandPending');
      this.socket.off('rrHeatMapUpdated');
      this.socket.off('aiProcessSaved');
      this.socket.off('migrateAiData');
    }

    if (error && error.trim() === 'io server disconnect') {
      window.isSessionExpired = true;
      emitter.emit(EMITTER_CONSTANTS.EXPIRED_TOKEN, 'request');
      this.socket = null;
    }

    // if (error && error.trim() === 'ping timeout' && !auth.token()) {
    //   this.disconnectSocket();
    //   this.socket = null;
    // }
    // if (error && error.trim() === 'io server disconnect') {
    //   emitter.emit(EMITTER_CONSTANTS.EXPIRED_TOKEN, 'request');
    //   this.socket = null;
    // }
  };

  reconnectListener = () => {
    console.log('on reconnect');
    this.socket.on('connect', this.connectListener);
    // window.location.reload();
    // Remove duplicate data
    const uniqRooms = _.uniqWith(this.rooms, _.isEqual);
    console.log('uniqRooms', uniqRooms);
    _.forEach(uniqRooms, (room) => {
      const { name, id } = room;
      switch (name) {
        case 'joinReportRoom': {
          this.sendJoinReportRoom(id);
          break;
        }
        default: {
          this.emitIntervalEvent(name, id);
          break;
        }
      }
    });
  };

  eventUpdatedListener = (msg) => {
    console.log('socket io - eventUpdatedListener', msg);
    if (msg.study?._id) {
      this.addQueueECGEventUpdate(msg.study?._id);
    }
    emitter.emit(EMITTER_CONSTANTS.UPDATE_EVENT_ECG, msg);
    if (auth.isCallCenter()) {
      this.addQueueHandleUpdateReport({ type: 'eventUpdated', data: msg });
    }
  };

  reportUpdatedListener = (msg) => {
    console.log('socket io - reportUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.REPORT_UPDATED, msg);
    if (auth.isCallCenter()) {
      this.addQueueHandleUpdateReport({ type: 'reportUpdated', data: msg });

      if (auth.isCallCenterSupervisor() || auth.isCallCenterQaLeader()) {
        this.addQueueHandleUpdateOverview({ type: 'reportUpdated', data: msg });
      }
    }
  };

  migrateAiDataListener = (msg) => {
    console.log('socket io - migrateAiDataListener', msg);
    emitter.emit(EMITTER_CONSTANTS.MIGRATE_AI_DATA_VER1_TO_VER2, msg);
  };

  newSessionListener = (msg) => {
    console.log('socket io - newSessionListener', msg);
    emitter.emit(EMITTER_CONSTANTS.NEW_SESSION, msg);
  };

  groupUpdatedListener = (msg) => {
    console.log('socket io - groupUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.GROUP_UPDATED, msg);
  };

  profileReadyListener = (msg) => {
    console.log('socket io - profileReadyListener', msg);
    emitter.emit(EMITTER_CONSTANTS.PROFILE_READY, msg);
  };

  beatsUpdatedListener = (msg) => {
    console.log('socket io - beatsUpdatedListener', msg);
    // logHandler.addLog('beatsUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.BEATSUPDATED_EVENT, msg);
  };

  eventsUpdatedListener = (msg) => {
    console.log('socket io - eventsUpdatedListener', msg);
    // logHandler.addLog('eventsUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.EVENTSUPDATED_EVENT, msg);
  };

  afibHrSummaryUpdatedListener = (msg) => {
    console.log('socket io - afibHrSummaryUpdatedListener', msg);
    // logHandler.addLog('afibHrSummaryUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.AFIB_HR_SUMMARY_UPDATED, msg);
  };

  dailySummaryUpdatedListener = (msg) => {
    console.log('socket io - dailySummaryUpdatedListener', msg);
    // logHandler.addLog('dailySummaryUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.DAILY_SUMMARY_UPDATED, msg);
  };

  holterProfileUpdatedListener = (msg) => {
    console.log('socket io - holterProfileUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.HOLTER_PROFILE_UPDATED, msg);
  };

  technicianCommentsUpdatedListener = (msg) => {
    console.log('socket io - technicianCommentsUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.TECHNICIAN_COMMENT_UPDATED, msg);
  };

  rrCellsReviewedListener = (msg) => {
    console.log('socket io - rrCellsReviewedListener', msg);
    // logHandler.addLog('rrCellsReviewed', msg);
    emitter.emit(EMITTER_CONSTANTS.RR_CELL_REVIEWED, msg);
  };

  commandProgressUpdatedListener = (msg) => {
    console.log('socket io - commandProgressUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.COMMAND_PROGRESS_UPDATED, msg);
  };

  commandExecutedListener = (msg) => {
    console.log('socket io - commandExecutedListener', msg);
    // logHandler.addLog('commandExecuted', msg);
    // logHandler.sendLog();
    emitter.emit(EMITTER_CONSTANTS.COMMAND_EXECUTED, msg);
  };

  commandPendingListener = (msg) => {
    console.log('socket io - commandPendingListener', msg);
    // logHandler.addLog('commandPending', msg);
    emitter.emit(EMITTER_CONSTANTS.COMMAND_PENDING, msg);
  };

  rrHeatMapUpdatedListener = (msg) => {
    console.log('socket io - rrHeatMapUpdatedListener', msg);
    // logHandler.addLog('rrHeatMapUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.RR_HEATMAP_UPDATED, msg);
  };

  aiProcessSavedListener = (msg) => {
    console.log('socket io - aiProcessSavedListener', msg);
    // logHandler.addLog('aiProcessSaved', msg);
    // logHandler.sendLog();
    emitter.emit(EMITTER_CONSTANTS.AI_PROCESS_SAVED, msg);
  };

  reCapturedEventsListener = async (msg) => {
    console.log('socket io - reCapturedEventsListener', msg);
    emitter.emit(EMITTER_CONSTANTS.RE_CAPTURE_EVENTS, msg);
  };

  roomUsersListener = (msg) => {
    console.log('socket io - roomUsersListener', msg);
    // logHandler.addLog('roomUsers', msg);
    if (msg.roomType === 'Event') {
      this.roomUsersEvent.push(msg);
    } else if (msg.roomType === 'Report') {
      this.roomUsersReport.push(msg);
    }
    if (!this.timeOutRoomEvent) {
      this.timeOutRoomEvent = setTimeout(() => {
        if (this.roomUsersEvent.length > 0) {
          emitter.emit(EMITTER_CONSTANTS.EVENT_ROOM_USER, this.roomUsersEvent.splice(0, this.roomUsersEvent.length));
        }
        if (this.roomUsersReport.length > 0) {
          emitter.emit(EMITTER_CONSTANTS.REPORT_ROOM_USER, this.roomUsersReport.splice(0, this.roomUsersReport.length));
        }
        this.timeOutRoomEvent = undefined;
      }, 1000);
    }
  };

  kickClientsByTokenListener = (msg) => {
    console.log('socket io - kickClientsByTokenListener', msg);
    emitter.emit(AppConstant.LOGOUT_REQUEST, 'request');
  };

  kickClientsByUsernameListener = (msg) => {
    console.log('socket io - kickClientsByUsernameListener', msg);
    emitter.emit(AppConstant.LOGOUT_REQUEST, 'request');
  };

  emitIntervalEvent = (status, id) => {
    console.log('EMITEVENT', status, id, this.isConnected);
    if (this.isConnected) {
      // console.log(`${this.TAG} ${status} `, id);
      this.socket.emit(status, id);
    } else {
      const interval = setInterval(() => {
        // console.log(`${this.TAG} ${status} `, id);
        if (this.isConnected) {
          this.socket.emit(status, id);
          clearInterval(interval);
        }
        if (!auth.token()) {
          clearInterval(interval);
        }
      }, 1000);
    }
  };

  handleStoreRooms = (name, id) => {
    if (!_.some(this.rooms, x => x.id === id)) {
      this.rooms.push({ name, id });
    }
  };

  emitRoom = (id) => {
    if (id && id !== 'undefined') {
      this.handleStoreRooms('room', id);
      this.emitIntervalEvent('room', id);
    }
  };

  addQueueECGEventUpdate = (studyId, msg = {}) => {
    this.queueECGEvent.push(studyId);
    if (!_.isEmpty(msg)) {
      this.queueNewEvent.push({ id: msg.id, stripImgs: msg.stripImgs });
    }
    if (!this.timeOutEventUpdate) {
      this.timeOutEventUpdate = setTimeout(() => {
        this.timeOutEventUpdate = undefined;
        emitter.emit(EMITTER_CONSTANTS.UPDATE_TOTAL_EVENTS, this.queueECGEvent.splice(0, this.queueECGEvent.length));
        if (this.queueNewEvent.length > 0) {
          emitter.emit(EMITTER_CONSTANTS.UPDATE_NEW_EVENT_ECG, this.queueNewEvent.splice(0, this.queueNewEvent.length));
        }
      }, 5000);
    }
  };

  addQueueHandleUpdateReport = (msg) => {
    this.queueReportUpdate.push(msg);
    if (!this.timeOutReportUpdate) {
      this.timeOutReportUpdate = setTimeout(() => {
        this.timeOutReportUpdate = undefined;
        if (this.updateReportReminder) {
          console.log('this.queueReportUpdate', this.queueReportUpdate);
          this.updateReportReminder(this.queueReportUpdate.splice(0, this.queueReportUpdate.length));
        }
      }, 1000);
    }
  };

  addQueueHandleUpdateOverview = (msg) => {
    this.queueOverviewUpdate.push(msg);
    if (!this.timeOutOverviewtUpdate) {
      this.timeOutOverviewtUpdate = setTimeout(() => {
        this.timeOutOverviewtUpdate = undefined;
        emitter.emit(EMITTER_CONSTANTS.UPDATE_OVERVIEW, this.queueOverviewUpdate.splice(0, this.queueOverviewUpdate.length));
      }, 15000);
    }
  };

  sendMessageToServer(event, data) {
    console.log('sendMessageToServer ', event, data);
    this.socket.emit(event, data);
  }

  // send join event room
  sendJoinEventRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    this.queueRoomEvent.push(msg);
    if (this.isConnected) {
      this.socket.emit('joinEventRoom', msg);
    } else if (!this.intervalJoinRoomEvent) {
      this.intervalJoinRoomEvent = setInterval(() => {
        if (this.isConnected) {
          const datas = _.assign([], this.queueRoomEvent);
          this.queueRoomEvent.splice(0, datas.length);
          _.forEach(datas, (e) => {
            this.socket.emit('joinEventRoom', e);
          });
          clearInterval(this.intervalJoinRoomEvent);
          this.intervalJoinRoomEvent = null;
        }
      }, 1000);
    }
  }

  // send join report room
  sendJoinReportRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    this.queueRoomReport.push(msg);
    if (this.isConnected) {
      console.log('[ ==> ] sendJoinReportRoom connected', msg);
      this.handleStoreRooms('joinReportRoom', msg.room);
      this.socket.emit('joinReportRoom', msg);
    } else if (!this.intervalJoinRoomReport) {
      this.intervalJoinRoomReport = setInterval(() => {
        if (this.isConnected) {
          const datas = _.assign([], this.queueRoomReport);
          this.queueRoomReport.splice(0, datas.length);
          // Remove duplicate data
          const uniqDatas = _.uniqWith(datas, _.isEqual);
          _.forEach(uniqDatas, (e) => {
            console.log('[ ==> ] sendJoinReportRoom', e);
            this.handleStoreRooms('joinReportRoom', e.room);
            this.socket.emit('joinReportRoom', e);
          });
          clearInterval(this.intervalJoinRoomReport);
          this.intervalJoinRoomReport = null;
        }
      }, 1000);
    }
  }

  sendLeaveReportRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    // *: Only use interval for emiting room
    // this.emitIntervalEvent('leaveReportRoom', msg);
    if (this.socket && this.isConnected) {
      console.log('[ ==> ] sendLeaveReportRoom', msg);
      _.remove(this.rooms, x => x.id === msg.room);
      this.socket.emit('leaveReportRoom', msg);
    }
  }

  sendLeaveEventRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    if (this.socket && this.isConnected) {
      _.remove(this.rooms, x => x.id === msg.room);
      this.socket.emit('leaveEventRoom', msg);
    }
  }

  disconnectSocket() {
    console.log('socket io disconnect', this.socket);
    if (this.socket) {
      this.socket.disconnect();
    }
    this.socket = null;
    this.rooms.length = 0;
  }
}

const staticSocket = new SocketClient();

export default staticSocket;
<script> 
$( document ).ready(function() {  
  
	//Change this ID's for the ID's of the pages you'd like to exclude.
	var exclude = ["d295a5b5-9761-4e54-a776-76fcbcafdd7e", 
                       "582eee08-77a6-4038-8e92-8c356f1bb64b", 
                       "dcd9aed3-ca05-4f9c-9fb9-4f09b44246e7"]; 
   
  	//Get page id.
	var pageId = window.ub.page.id
  	//Compare pageId to array
  	if (jQuery.inArray(pageId, exclude)=='-1') {
      
    		//ADD YOUR SCRIPT HERE
      
        }
});
</script>
////////////////**** FILTER FUNCTION*****///////////////////
const MyNum = [1,2,3,4,5,6,7,8,9,10]
   
   
   
const  mynums = MyNum
                .map((num) => num  * 10)
                .map((num) => num  + 1)
                .filter((num) => num  >= 40)
                
console.log(mynums);
                
//////// reduce function ///////////////////////
                
const NUM = [1, 2, 3, 4];
const mytotal = NUM.reduce(function (acc, currval) {
    console.log(`acc: ${acc} and currval: ${currval}`);
    return acc + currval;
}, 0); // zero is the acc's initial value
console.log(mytotal);

const mytot = NUM.reduce((acc, curr) => acc+curr, 0 )
console.log(mytot);

const shoppingCart = [
    {
        itemName: "js course",
        price: 2999
    },
    {
        itemName: "py course",
        price: 999
    },
    {
        itemName: "mobile dev course",
        price: 5999
    },
    {
        itemName: "data science course",
        price: 12999
    },
]

const priceToPay = shoppingCart.reduce((acc, item) => acc + item.price, 0)

console.log(priceToPay);
    $cnpp = cnplanpriceTable::getOneByPlan('A_PP_FREE1');

    $ads = cnadTable::getInstance()
      ->createQuery()
      ->andWhere('userid = ?', 1107924)
      ->andWhere('hw_pay_plan LIKE ?', '%A_PA_FREE1%')
      ->execute([], Doctrine::HYDRATE_ON_DEMAND);
    $this->log('Found ' . count($ads) . ' ads');

    foreach ( $ads as $cnad )
    {
      $cnad->setPlan($cnpp);
      $cnad->save();

      $cnexp = cnexpirationTable::getItem($cnad, 'ad_plan');
      $cnexp->setValue('A_PP_FREE1');
      $cnexp->save();
      $this->log('Processed ' . $cnad->getLinkId());
    }
const getWeekOfYear = (date: Date): number => {
  const startOfYear = new Date(date.getFullYear(), 0, 1);
  const days = Math.floor(
    (date.getTime() - startOfYear.getTime()) / (24 * 60 * 60 * 1000)
  );
  return Math.ceil((days + startOfYear.getDay() + 1) / 7);
};
///////////***********FILTER , MAP AND REDUCE ********////////////

 const coding = ["js", "ruby", "java", "python", "cpp"]


 const values = coding.forEach( (item) => {
   console.log(item);
     return item
 } )

 console.log(values);

/////////////////*********** FILTER FUNCTION **********************////////////
const myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// const newNums = myNums.filter( (num) => {
//  return num > 4
// } )

const newNums = []

 myNums.forEach( (num) => {
     if (num > 4) {
         newNums.push(num)
    }
 } )

console.log(newNums);


const books = [
    { title: 'Book One', genre: 'Fiction', publish: 1981, edition: 2004 },
    { title: 'Book Two', genre: 'Non-Fiction', publish: 1992, edition: 2008 },
    { title: 'Book Three', genre: 'History', publish: 1999, edition: 2007 },
    { title: 'Book Four', genre: 'Non-Fiction', publish: 1989, edition: 2010 },
    { title: 'Book Five', genre: 'Science', publish: 2009, edition: 2014 },
    { title: 'Book Six', genre: 'Fiction', publish: 1987, edition: 2010 },
    { title: 'Book Seven', genre: 'History', publish: 1986, edition: 1996 },
    { title: 'Book Eight', genre: 'Science', publish: 2011, edition: 2016 },
    { title: 'Book Nine', genre: 'Non-Fiction', publish: 1981, edition: 1989 },
  ];

  let userBooks  = books.filter( (bk) => bk.genre === 'History')
  console.log(userBooks);
  
  userBook = books.filter( (bk) => { 
    return bk.publish >= 1995 && bk.genre === "History"
})
  console.log(userBook);
#include <iostream>

int main() {
    int a, b, f1=0, f2=1, i;

    std::cout << "Введите число a: ";
    std::cin >> a;
    
    std::cout << "Введите число b: ";
    std::cin >> b;
    
    for(i = a; i <= b; i++)
        std::cout << i << " " ;
        
    std::cout << std::endl;    
    
    if( a == 0 )
        std::cout << 0 << " " ;
        
    while( f2 <= b ){
        if( f2 >= a )
            std::cout << f2 << " " ;
        i = f2;
        f2 = f1 + f2;
        f1 = i;
        }    
        
    return 0;
}
if (!function_exists('media_sideload_image')) {
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    require_once(ABSPATH . 'wp-admin/includes/media.php');
}


add_action('gform_after_submission_2', 'create_gallery_post_after_submission', 10, 2);
function create_gallery_post_after_submission($entry, $form) {
    // Include necessary functions for media handling
    if (!function_exists('media_sideload_image')) {
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/media.php');
    }

    // Define your custom post type
    $post_type = 'gallery';

    // Prepare post data
    $post_data = array(
        'post_title'   => rgar($entry, '5'), // Assuming field ID 5 is the title
        'post_content' => '', // Assuming field ID 2 is the content
        'post_status'  => 'publish',
        'post_type'    => $post_type,
    );

    // Insert the post into the database
    $post_id = wp_insert_post($post_data);

    // Get the image URLs from entry
    $image_urls = json_decode(rgar($entry, '1')); // Assuming field ID 1 contains the JSON array string
    $image_ids = array(); // Array to hold the IDs of uploaded images

    // Loop through each image URL
    if (is_array($image_urls)) {
        foreach ($image_urls as $image_url) {
            // Upload the image to the Media Library
            $image_id = media_sideload_image($image_url, $post_id, null, 'id');
            if (!is_wp_error($image_id)) {
                $image_ids[] = $image_id; // Collect the image ID
            }
        }
    }

    // Optionally, you can set post meta for the uploaded images
    if (!empty($image_ids)) {
        update_post_meta($post_id, 'gallery_images', $image_ids); // Store the array of image IDs
    }
}


add_filter('woocommerce_get_breadcrumb', 'precise_custom_woocommerce_breadcrumbs', 20, 2);
function precise_custom_woocommerce_breadcrumbs($crumbs, $breadcrumb) {
    // הסרת עמוד הבית
    if (isset($crumbs[0]) && $crumbs[0][0] == get_bloginfo('name')) {
        array_shift($crumbs);
    }

    // אם אנחנו בעמוד מוצר
    if (is_product()) {
        $product = wc_get_product();
        $product_categories = get_the_terms($product->get_id(), 'product_cat');
       
        if ($product_categories) {
            // מציאת הקטגוריה העמוקה ביותר
            $deepest_category = null;
            foreach ($product_categories as $category) {
                if (!$deepest_category || count(get_ancestors($category->term_id, 'product_cat')) >
                    count(get_ancestors($deepest_category->term_id, 'product_cat'))) {
                    $deepest_category = $category;
                }
            }

            if ($deepest_category) {
                // הכנת מערך חדש של פירורי לחם
                $new_crumbs = [];
               
                // קבלת ההורים של הקטגוריה
                $term_parents = get_ancestors($deepest_category->term_id, 'product_cat');
                $term_parents = array_reverse($term_parents);

                // הוספת ההורים
                foreach ($term_parents as $parent_id) {
                    $parent_term = get_term($parent_id, 'product_cat');
                    $new_crumbs[] = [$parent_term->name, get_term_link($parent_term)];
                }

                // הוספת הקטגוריה העמוקה ביותר
                $new_crumbs[] = [$deepest_category->name, get_term_link($deepest_category)];

                // הוספת שם המוצר
                $new_crumbs[] = [$product->get_name(), get_permalink($product)];

                // החלפת הפירורי לחם המקוריים
                $crumbs = $new_crumbs;
            }
        }
    }

    // אם אנחנו בדף קטגוריה
    if (is_product_category()) {
        $current_category = get_queried_object();
        $ancestors = get_ancestors($current_category->term_id, 'product_cat');
        $ancestors = array_reverse($ancestors);

        // הכנת מערך חדש של פירורי לחם
        $new_crumbs = [];

        // הוספת ההורים
        foreach ($ancestors as $ancestor_id) {
            $ancestor_term = get_term($ancestor_id, 'product_cat');
            $new_crumbs[] = [$ancestor_term->name, get_term_link($ancestor_term)];
        }

        // הוספת הקטגוריה הנוכחית
        $new_crumbs[] = [$current_category->name, get_term_link($current_category)];

        // החלפת הפירורי לחם המקוריים
        $crumbs = $new_crumbs;
    }

    return $crumbs;
// import React, { useRef, useState, useEffect } from 'react'
// import { HotTable } from '@handsontable/react'
// import 'handsontable/dist/handsontable.full.min.css'
// import Handsontable from 'handsontable'
// import {
//   registerControl,
//   RegisterControlProps,
//   RegisteredControlProperties,
// } from '../hoc/registerControl'
// import { CustomContentRenderer } from './utils/customButtonRenderer'
// import { hyperformulaInstance, sheetId } from './utils/hyperformulaConfig'
// import { reformatDate, reformatCurrency } from './utils/formatters'
// import { SpreadsheetProperties } from '@components/features/FormBuilder/FormBuilderFieldProperties/Spreadsheet/types'
// import { registerAllCellTypes } from 'handsontable/cellTypes'
// import { registerAllPlugins } from 'handsontable/plugins'
// import { useFormBuilderWorksheetGrid } from '../../hooks/useFormBuilderWorksheetGrid'
// import { createSpreadsheetDefaultValue } from '../../FormBuilderFieldProperties/Spreadsheet/constants'
// import { useFormBuilder } from '../../hooks/useFormBuilder'
// import { useFormService } from '../../hooks/useFormService'

// registerAllCellTypes()
// registerAllPlugins()

// type Properties = RegisteredControlProperties &
//   SpreadsheetProperties & {
//     externalVariables?: {
//       [key: string]: {
//         propertyName?: string
//         defaultValue?: number
//       }
//     }
//   }

// const SpreadsheetControl: React.FC<RegisterControlProps<Properties>> = (
//   props
// ) => {
//   const hotTableRef = useRef<any>(null)
//   const containerRef = useRef<HTMLDivElement>(null)

//   const { rows = 1, columns = 1 } = props.properties || {}

//   const DEFAULT_COLUMN_WIDTH = 100
//   const DEFAULT_ROW_HEIGHT = 25

//   const defaultMeta = {
//     data: createSpreadsheetDefaultValue(rows, columns),
//     cellFormats: {} as { [key: string]: 'date' | 'currency' | undefined },
//     mergeCellsConfig: [],
//   }

//   const meta = props.properties?.meta || defaultMeta
//   const { actions: formBuilderWorksheetActions } = useFormBuilderWorksheetGrid()
//   const { actions, data: formBuilderData } = useFormBuilder()
//   const { watch } = useFormService()
//   const formData = watch()

//   if (!actions || !actions.getAllFields) {
//   }

//   const [data, setData] = useState(() => JSON.parse(JSON.stringify(meta.data)))
//   const [cellFormats, setCellFormats] = useState(meta.cellFormats)
//   const [mergeCellsConfig, setMergeCellsConfig] = useState(
//     meta.mergeCellsConfig
//   )

//   useEffect(() => {
//     if (formBuilderData?.fields) {
//       const existingExpressions = hyperformulaInstance.listNamedExpressions()

//       formBuilderData.fields.forEach((field) => {
//         const propertyName = field.properties?.propertyName
//         const defaultValue = Number(field.properties?.defaultValue || 0)

//         if (propertyName) {
//           if (!existingExpressions.includes(propertyName)) {
//             hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
//           } else {
//             hyperformulaInstance.changeNamedExpression(
//               propertyName,
//               defaultValue
//             )
//           }
//         }
//       })

//       hyperformulaInstance.rebuildAndRecalculate()
//     }
//   }, [formBuilderData])

//   useEffect(() => {
//     if (props.externalVariables) {
//       const existingExpressions = new Set(
//         hyperformulaInstance.listNamedExpressions()
//       )

//       Object.entries(props.externalVariables).forEach(([key, property]) => {
//         const typedProperty = property as {
//           propertyName?: string
//           defaultValue?: number
//         }

//         const variableName = typedProperty.propertyName || key
//         const value = Number(typedProperty.defaultValue || 0)

//         if (!existingExpressions.has(variableName)) {
//           try {
//             hyperformulaInstance.addNamedExpression(
//               variableName,
//               value,
//               sheetId
//             )
//             existingExpressions.add(variableName)
//           } catch (error) {
//             console.error(
//               `Error adding named expression ${variableName}:`,
//               error
//             )
//           }
//         } else {
//           try {
//             hyperformulaInstance.changeNamedExpression(
//               variableName,
//               value,
//               sheetId
//             )
//           } catch (error) {
//             console.error(
//               `Error updating named expression ${variableName}:`,
//               error
//             )
//           }
//         }
//       })

//       try {
//         hyperformulaInstance.rebuildAndRecalculate()
//       } catch (error) {
//         console.error(
//           'Error during HyperFormula rebuild and recalculation:',
//           error
//         )
//       }
//     }
//   }, [props.externalVariables])

//   useEffect(() => {
//     if (formBuilderData) {
//       const existingExpressions = hyperformulaInstance.listNamedExpressions()

//       Object.entries(formBuilderData).forEach(([key, value]) => {
//         const numericValue = Number(value) || 0

//         if (!existingExpressions.includes(key)) {
//           hyperformulaInstance.addNamedExpression(key, numericValue)
//         } else {
//           hyperformulaInstance.changeNamedExpression(key, numericValue)
//         }
//       })

//       hyperformulaInstance.rebuildAndRecalculate()
//     }
//   }, [formBuilderData])

//   useEffect(() => {
//     if (formBuilderData?.fields) {
//       const existingExpressions = new Set(
//         hyperformulaInstance.listNamedExpressions()
//       )

//       formBuilderData.fields.forEach((field) => {
//         const propertyName = field.properties?.propertyName
//         const defaultValue = Number(field.properties?.defaultValue || 0)

//         if (propertyName && !existingExpressions.has(propertyName)) {
//           try {
//             hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
//             existingExpressions.add(propertyName)
//           } catch (error) {
//             console.error(
//               `Error adding named expression for ${propertyName}: ${error}`
//             )
//           }
//         } else if (propertyName) {
//           try {
//             hyperformulaInstance.changeNamedExpression(
//               propertyName,
//               defaultValue
//             )
//           } catch (error) {
//             console.error(
//               `Error updating named expression for ${propertyName}: ${error}`
//             )
//           }
//         }
//       })

//       try {
//         hyperformulaInstance.rebuildAndRecalculate()
//       } catch (error) {
//         console.error(
//           'Error during HyperFormula rebuild and recalculation:',
//           error
//         )
//       }
//     }
//   }, [formBuilderData?.fields])

//   useEffect(() => {
//     if (formData && Object.keys(formData).length > 0) {
//       const existingExpressions = hyperformulaInstance.listNamedExpressions()

//       Object.entries(formData).forEach(([key, value]) => {
//         if (!existingExpressions.includes(key)) {
//           hyperformulaInstance.addNamedExpression(key, Number(value) || 0)
//         } else {
//           hyperformulaInstance.changeNamedExpression(key, Number(value) || 0)
//         }
//       })

//       try {
//         hyperformulaInstance.rebuildAndRecalculate()
//       } catch (error) {}
//     }
//   }, [formData])

//   useEffect(() => {
//     const adjustedData = adjustDataDimensions(data, rows, columns)
//     if (JSON.stringify(data) !== JSON.stringify(adjustedData)) {
//       setData(adjustedData)
//     }
//   }, [rows, columns])

//   const adjustDataDimensions = (
//     currentData: any[][],
//     rows: number,
//     columns: number
//   ) => {
//     const newData = currentData.map((row) => [...row])
//     if (newData.length < rows) {
//       for (let i = newData.length; i < rows; i++) {
//         newData.push(Array(columns).fill(null))
//       }
//     } else if (newData.length > rows) {
//       newData.length = rows
//     }
//     newData.forEach((row) => {
//       if (row.length < columns) {
//         row.push(...Array(columns - row.length).fill(null))
//       } else if (row.length > columns) {
//         row.length = columns
//       }
//     })
//     return newData
//   }

//   const handleAfterChange = (changes: any, source: string) => {
//     if (!changes || source === 'loadData') return

//     const validSheetId = sheetId ?? 0

//     changes.forEach(([row, col, oldValue, newValue]: any) => {
//       if (
//         newValue &&
//         typeof newValue === 'string' &&
//         newValue.startsWith('=')
//       ) {
//         try {
//           hyperformulaInstance.setCellContents(
//             { sheet: validSheetId, row, col },
//             [[newValue]]
//           )
//         } catch (error) {
//           console.error('Error setting formula:', error)
//         }
//       }
//     })

//     const updatedData = hotTableRef.current?.hotInstance?.getData()
//     if (JSON.stringify(data) !== JSON.stringify(updatedData)) {
//       setData(updatedData)
//       updateFieldProperties({ data: updatedData })
//     }
//   }

//   const handleMergeCells = () => {
//     const hotInstance = hotTableRef.current?.hotInstance
//     const selected = hotInstance?.getSelected()
//     if (selected) {
//       const [startRow, startCol, endRow, endCol] = selected[0]
//       const newMerge = {
//         row: startRow,
//         col: startCol,
//         rowspan: endRow - startRow + 1,
//         colspan: endCol - startCol + 1,
//       }

//       const updatedMergeCellsConfig = [...mergeCellsConfig, newMerge]
//       hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
//       setMergeCellsConfig(updatedMergeCellsConfig)

//       updateFieldProperties({
//         data,
//         cellFormats,
//         mergeCellsConfig: updatedMergeCellsConfig,
//       })
//     }
//   }

//   const handleUnmergeCells = () => {
//     const hotInstance = hotTableRef.current?.hotInstance
//     const selected = hotInstance?.getSelected()
//     if (selected) {
//       const [startRow, startCol] = selected[0]
//       const mergeCellsPlugin = hotInstance.getPlugin('mergeCells')
//       mergeCellsPlugin.unmerge(startRow, startCol)

//       const updatedMergeCellsConfig = mergeCellsConfig.filter(
//         (cell) => cell.row !== startRow || cell.col !== startCol
//       )
//       hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
//       setMergeCellsConfig(updatedMergeCellsConfig)

//       updateFieldProperties({
//         data,
//         cellFormats,
//         mergeCellsConfig: updatedMergeCellsConfig,
//       })
//     }
//   }

//   const handleSetAsDate = () => {
//     const selected = hotTableRef.current?.hotInstance.getSelected()
//     if (selected) {
//       const [row, col] = selected[0]
//       const newFormats = { ...cellFormats, [`${row}-${col}`]: 'date' as const }
//       setCellFormats(newFormats)
//       updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
//     }
//   }

//   const handleSetAsCurrency = () => {
//     const selected = hotTableRef.current?.hotInstance.getSelected()
//     if (selected) {
//       const [row, col] = selected[0]
//       const newFormats = {
//         ...cellFormats,
//         [`${row}-${col}`]: 'currency' as const,
//       }
//       setCellFormats(newFormats)
//       updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
//     }
//   }

//   const updateFieldProperties = (
//     updatedMeta: Partial<SpreadsheetProperties['meta']>
//   ) => {
//     if (!props?.runtime) {
//       const safeData = data ?? []

//       formBuilderWorksheetActions?.setFieldConfigProperty(props.config?.id!, {
//         meta: {
//           data: [...safeData.map((row: any) => (row ? [...row] : []))],
//           cellFormats: { ...cellFormats },
//           mergeCellsConfig: [...mergeCellsConfig],
//           ...updatedMeta,
//         },
//       } as Properties)
//     }
//   }

//   const cellsHandler = (row: number, col: number) => {
//     const cellProperties = {} as Handsontable.CellProperties
//     cellProperties.width = DEFAULT_COLUMN_WIDTH
//     cellProperties.height = DEFAULT_ROW_HEIGHT

//     // Check if the cell format exists, or default to undefined
//     const format = cellFormats?.[`${row}-${col}`]

//     if (format === 'date') {
//       cellProperties.renderer = (
//         instance,
//         td,
//         row,
//         col,
//         prop,
//         value,
//         cellProperties
//       ) =>
//         CustomContentRenderer(instance, td, row, col, () => {
//           const span = document.createElement('span')
//           span.innerText = reformatDate(
//             instance.getDataAtCell(row, col) as string
//           )
//           return span
//         })
//     } else if (format === 'currency') {
//       cellProperties.renderer = (
//         instance,
//         td,
//         row,
//         col,
//         prop,
//         value,
//         cellProperties
//       ) =>
//         CustomContentRenderer(instance, td, row, col, () => {
//           const span = document.createElement('span')
//           span.innerText = reformatCurrency(
//             instance.getDataAtCell(row, col) as string
//           )
//           return span
//         })
//     }

//     return cellProperties
//   }

//   return (
//     <div
//       ref={containerRef}
//       className="h-[400px] w-1/2 resize-x overflow-auto border md:w-full"
//       style={{ minWidth: '50%', maxWidth: '100%', resize: 'horizontal' }}
//       onMouseDown={(e) => e.stopPropagation()}
//     >
//       <HotTable
//         id="mySpreadsheet"
//         data={data}
//         colHeaders={true}
//         rowHeaders={true}
//         width="100%"
//         height="100%"
//         selectionMode="multiple"
//         copyPaste={true}
//         contextMenu={{
//           items: {
//             row_above: {},
//             row_below: {},
//             col_left: {},
//             col_right: {},
//             remove_row: {},
//             remove_col: {},
//             clear_column: {},
//             mergeCells: { name: 'Merge Cells', callback: handleMergeCells },
//             unmergeCells: {
//               name: 'Unmerge Cells',
//               callback: handleUnmergeCells,
//             },
//             set_as_date: { name: 'Set as Date', callback: handleSetAsDate },
//             set_as_currency: {
//               name: 'Set as Currency',
//               callback: handleSetAsCurrency,
//             },
//           },
//         }}
//         ref={hotTableRef}
//         afterChange={handleAfterChange}
//         persistentState={true}
//         licenseKey="non-commercial-and-evaluation"
//         manualColumnResize={false}
//         manualRowResize={false}
//         autoColumnSize={false}
//         autoRowSize={false}
//         stretchH="all"
//         mergeCells={mergeCellsConfig}
//         formulas={{ engine: hyperformulaInstance }}
//         cells={cellsHandler}
//         colWidths={DEFAULT_COLUMN_WIDTH}
//         rowHeights={DEFAULT_ROW_HEIGHT}
//       />
//     </div>
//   )
// }

// export default registerControl<Properties>(SpreadsheetControl, {
//   noDisplayLabel: true,
// })

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// import React, { useRef, useState, useEffect } from 'react'
// import { HotTable } from '@handsontable/react'
// import 'handsontable/dist/handsontable.full.min.css'
// import Handsontable from 'handsontable'
// import {
//   registerControl,
//   RegisterControlProps,
//   RegisteredControlProperties,
// } from '../hoc/registerControl'
// import { CustomContentRenderer } from './utils/customButtonRenderer'
// import { hyperformulaInstance, sheetId } from './utils/hyperformulaConfig'
// import { reformatDate, reformatCurrency } from './utils/formatters'
// import { SpreadsheetProperties } from '@components/features/FormBuilder/FormBuilderFieldProperties/Spreadsheet/types'
// import { registerAllCellTypes } from 'handsontable/cellTypes'
// import { registerAllPlugins } from 'handsontable/plugins'
// import { useFormBuilderWorksheetGrid } from '../../hooks/useFormBuilderWorksheetGrid'
// import { createSpreadsheetDefaultValue } from '../../FormBuilderFieldProperties/Spreadsheet/constants'
// import { useFormBuilder } from '../../hooks/useFormBuilder'
// import { useFormService } from '../../hooks/useFormService'

// registerAllCellTypes()
// registerAllPlugins()

// type Properties = RegisteredControlProperties &
//   SpreadsheetProperties & {
//     externalVariables?: {
//       [key: string]: {
//         propertyName?: string
//         defaultValue?: number
//       }
//     }
//   }

// const SpreadsheetControl: React.FC<RegisterControlProps<Properties>> = (
//   props
// ) => {
//   const hotTableRef = useRef<any>(null)
//   const containerRef = useRef<HTMLDivElement>(null)

//   const { rows = 1, columns = 1 } = props.properties || {}

//   const DEFAULT_COLUMN_WIDTH = 100
//   const DEFAULT_ROW_HEIGHT = 25

//   const defaultMeta = {
//     data: createSpreadsheetDefaultValue(rows, columns),
//     cellFormats: {} as { [key: string]: 'date' | 'currency' | undefined },
//     mergeCellsConfig: [],
//   }

//   const meta = props.properties?.meta || defaultMeta
//   const { actions: formBuilderWorksheetActions } = useFormBuilderWorksheetGrid()
//   const { actions, data: formBuilderData } = useFormBuilder()
//   const { watch } = useFormService()
//   const formData = watch()

//   if (!actions || !actions.getAllFields) {
//   }

//   const [data, setData] = useState(() => JSON.parse(JSON.stringify(meta.data)))
//   const [cellFormats, setCellFormats] = useState(meta.cellFormats)
//   const [mergeCellsConfig, setMergeCellsConfig] = useState(
//     meta.mergeCellsConfig
//   )

//   useEffect(() => {
//     console.log('Initializing meta from props:', props.properties?.meta)
//     const initialMeta = props.properties?.meta || defaultMeta
//     setData(JSON.parse(JSON.stringify(initialMeta.data)))
//     setCellFormats(initialMeta.cellFormats)
//     setMergeCellsConfig(initialMeta.mergeCellsConfig)
//   }, [props.properties?.meta])

//   useEffect(() => {
//     console.log('Data updated:', data)
//   }, [data])

//   useEffect(() => {
//     console.log('Cell formats updated:', cellFormats)
//   }, [cellFormats])

//   useEffect(() => {
//     console.log('Merge cells configuration updated:', mergeCellsConfig)
//   }, [mergeCellsConfig])

//   useEffect(() => {
//     if (formBuilderData?.fields) {
//       const existingExpressions = hyperformulaInstance.listNamedExpressions()

//       formBuilderData.fields.forEach((field) => {
//         const propertyName = field.properties?.propertyName
//         const defaultValue = Number(field.properties?.defaultValue || 0)

//         if (propertyName) {
//           if (!existingExpressions.includes(propertyName)) {
//             hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
//           } else {
//             hyperformulaInstance.changeNamedExpression(
//               propertyName,
//               defaultValue
//             )
//           }
//         }
//       })

//       hyperformulaInstance.rebuildAndRecalculate()
//     }
//   }, [formBuilderData])

//   useEffect(() => {
//     if (props.externalVariables) {
//       const existingExpressions = new Set(
//         hyperformulaInstance.listNamedExpressions()
//       )

//       Object.entries(props.externalVariables).forEach(([key, variable]) => {
//         const typedVariable = variable as {
//           propertyName?: string
//           defaultValue?: number
//         }

//         const variableName = typedVariable.propertyName || key
//         const value = Number(typedVariable.defaultValue || 0)

//         if (!existingExpressions.has(variableName)) {
//           hyperformulaInstance.addNamedExpression(variableName, value, sheetId)
//         } else {
//           hyperformulaInstance.changeNamedExpression(
//             variableName,
//             value,
//             sheetId
//           )
//         }
//       })

//       hyperformulaInstance.rebuildAndRecalculate()
//       syncSpreadsheetWithEngine()
//     }
//   }, [props.externalVariables])

//   useEffect(() => {
//     if (formBuilderData) {
//       const existingExpressions = hyperformulaInstance.listNamedExpressions()

//       Object.entries(formBuilderData).forEach(([key, value]) => {
//         const numericValue = Number(value) || 0

//         if (!existingExpressions.includes(key)) {
//           hyperformulaInstance.addNamedExpression(key, numericValue)
//         } else {
//           hyperformulaInstance.changeNamedExpression(key, numericValue)
//         }
//       })

//       hyperformulaInstance.rebuildAndRecalculate()
//     }
//   }, [formBuilderData])

//   useEffect(() => {
//     if (formBuilderData?.fields) {
//       const existingExpressions = new Set(
//         hyperformulaInstance.listNamedExpressions()
//       )

//       formBuilderData.fields.forEach((field) => {
//         const propertyName = field.properties?.propertyName
//         const defaultValue = Number(field.properties?.defaultValue || 0)

//         if (propertyName && !existingExpressions.has(propertyName)) {
//           try {
//             hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
//             existingExpressions.add(propertyName)
//           } catch (error) {
//             console.error(
//               `Error adding named expression for ${propertyName}: ${error}`
//             )
//           }
//         } else if (propertyName) {
//           try {
//             hyperformulaInstance.changeNamedExpression(
//               propertyName,
//               defaultValue
//             )
//           } catch (error) {
//             console.error(
//               `Error updating named expression for ${propertyName}: ${error}`
//             )
//           }
//         }
//       })

//       try {
//         hyperformulaInstance.rebuildAndRecalculate()
//       } catch (error) {
//         console.error(
//           'Error during HyperFormula rebuild and recalculation:',
//           error
//         )
//       }
//     }
//   }, [formBuilderData?.fields])

//   useEffect(() => {
//     if (formData && Object.keys(formData).length > 0) {
//       const existingExpressions = hyperformulaInstance.listNamedExpressions()

//       Object.entries(formData).forEach(([key, value]) => {
//         if (!existingExpressions.includes(key)) {
//           hyperformulaInstance.addNamedExpression(key, Number(value) || 0)
//         } else {
//           hyperformulaInstance.changeNamedExpression(key, Number(value) || 0)
//         }
//       })

//       try {
//         hyperformulaInstance.rebuildAndRecalculate()
//       } catch (error) {}
//     }
//   }, [formData])

//   useEffect(() => {
//     const adjustedData = adjustDataDimensions(data, rows, columns)
//     if (JSON.stringify(data) !== JSON.stringify(adjustedData)) {
//       setData(adjustedData)
//       updateFieldProperties({ data: adjustedData })
//     }
//   }, [rows, columns])

//   const adjustDataDimensions = (
//     currentData: any[][],
//     rows: number,
//     columns: number
//   ) => {
//     const newData = currentData.map((row) => [...row])
//     if (newData.length < rows) {
//       for (let i = newData.length; i < rows; i++) {
//         newData.push(Array(columns).fill(null))
//       }
//     } else if (newData.length > rows) {
//       newData.length = rows
//     }
//     newData.forEach((row) => {
//       if (row.length < columns) {
//         row.push(...Array(columns - row.length).fill(null))
//       } else if (row.length > columns) {
//         row.length = columns
//       }
//     })
//     return newData
//   }
//   const syncSpreadsheetWithEngine = () => {
//     if (hotTableRef.current?.hotInstance) {
//       const updatedData = hyperformulaInstance.getSheetValues(sheetId)
//       console.log('Syncing spreadsheet with engine. Updated Data:', updatedData)
//       hotTableRef.current.hotInstance.loadData(updatedData)
//     }
//   }

//   const handleAfterChange = (changes: any, source: string) => {
//     console.log('After Change Triggered. Source:', source)
//     console.log('Changes:', changes)

//     if (!changes || source === 'loadData') return

//     const validSheetId = sheetId ?? 0

//     changes.forEach(([row, col, oldValue, newValue]: any) => {
//       console.log(
//         `Updating cell [${row}, ${col}] from ${oldValue} to ${newValue}`
//       )
//       if (
//         newValue &&
//         typeof newValue === 'string' &&
//         newValue.startsWith('=')
//       ) {
//         hyperformulaInstance.setCellContents(
//           { sheet: validSheetId, row, col },
//           [[newValue]]
//         )
//       } else {
//         hyperformulaInstance.setCellContents(
//           { sheet: validSheetId, row, col },
//           [[newValue || null]]
//         )
//       }
//     })

//     // Recalculate and sync data
//     hyperformulaInstance.rebuildAndRecalculate()
//     console.log(
//       'Recalculated HyperFormula Instance:',
//       hyperformulaInstance.getSheetValues(sheetId)
//     )
//     syncSpreadsheetWithEngine()
//   }

//   const handleMergeCells = () => {
//     const hotInstance = hotTableRef.current?.hotInstance
//     const selected = hotInstance?.getSelected()
//     if (selected) {
//       const [startRow, startCol, endRow, endCol] = selected[0]
//       const newMerge = {
//         row: startRow,
//         col: startCol,
//         rowspan: endRow - startRow + 1,
//         colspan: endCol - startCol + 1,
//       }

//       const updatedMergeCellsConfig = [...mergeCellsConfig, newMerge]
//       hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
//       setMergeCellsConfig(updatedMergeCellsConfig)

//       updateFieldProperties({
//         data,
//         cellFormats,
//         mergeCellsConfig: updatedMergeCellsConfig,
//       })
//     }
//   }

//   const handleUnmergeCells = () => {
//     const hotInstance = hotTableRef.current?.hotInstance
//     const selected = hotInstance?.getSelected()
//     if (selected) {
//       const [startRow, startCol] = selected[0]
//       const mergeCellsPlugin = hotInstance.getPlugin('mergeCells')
//       mergeCellsPlugin.unmerge(startRow, startCol)

//       const updatedMergeCellsConfig = mergeCellsConfig.filter(
//         (cell) => cell.row !== startRow || cell.col !== startCol
//       )
//       hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
//       setMergeCellsConfig(updatedMergeCellsConfig)

//       updateFieldProperties({
//         data,
//         cellFormats,
//         mergeCellsConfig: updatedMergeCellsConfig,
//       })
//     }
//   }

//   const handleSetAsDate = () => {
//     const selected = hotTableRef.current?.hotInstance.getSelected()
//     if (selected) {
//       const [row, col] = selected[0]
//       const newFormats = { ...cellFormats, [`${row}-${col}`]: 'date' as const }
//       setCellFormats(newFormats)
//       updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
//     }
//   }

//   const handleSetAsCurrency = () => {
//     const selected = hotTableRef.current?.hotInstance.getSelected()
//     if (selected) {
//       const [row, col] = selected[0]
//       const newFormats = {
//         ...cellFormats,
//         [`${row}-${col}`]: 'currency' as const,
//       }
//       setCellFormats(newFormats)
//       updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
//     }
//   }
//   const updateFieldProperties = (
//     updatedMeta: Partial<SpreadsheetProperties['meta']>
//   ) => {
//     console.log('Updating field properties with meta:', updatedMeta)
//     console.log('Current data:', data)
//     if (!props.runtime) {
//       formBuilderWorksheetActions?.setFieldConfigProperty(props.config?.id!, {
//         meta: {
//           data: [...data.map((row: any) => (row ? [...row] : []))],
//           cellFormats: { ...cellFormats },
//           mergeCellsConfig: [...mergeCellsConfig],
//           ...updatedMeta,
//         },
//       } as Properties)
//     }
//   }

//   const cellsHandler = (row: number, col: number) => {
//     const cellProperties = {} as Handsontable.CellProperties
//     cellProperties.width = DEFAULT_COLUMN_WIDTH
//     cellProperties.height = DEFAULT_ROW_HEIGHT

//     // Check if the cell format exists, or default to undefined
//     const format = cellFormats?.[`${row}-${col}`]

//     if (format === 'date') {
//       cellProperties.renderer = (
//         instance,
//         td,
//         row,
//         col,
//         prop,
//         value,
//         cellProperties
//       ) =>
//         CustomContentRenderer(instance, td, row, col, () => {
//           const span = document.createElement('span')
//           span.innerText = reformatDate(
//             instance.getDataAtCell(row, col) as string
//           )
//           return span
//         })
//     } else if (format === 'currency') {
//       cellProperties.renderer = (
//         instance,
//         td,
//         row,
//         col,
//         prop,
//         value,
//         cellProperties
//       ) =>
//         CustomContentRenderer(instance, td, row, col, () => {
//           const span = document.createElement('span')
//           span.innerText = reformatCurrency(
//             instance.getDataAtCell(row, col) as string
//           )
//           return span
//         })
//     }

//     return cellProperties
//   }

//   return (
//     <div
//       ref={containerRef}
//       className="h-[400px] w-1/2 resize-x overflow-auto border md:w-full"
//       style={{ minWidth: '50%', maxWidth: '100%', resize: 'horizontal' }}
//       onMouseDown={(e) => e.stopPropagation()}
//     >
//       <HotTable
//         id="mySpreadsheet"
//         data={data}
//         colHeaders={true}
//         rowHeaders={true}
//         width="100%"
//         height="100%"
//         selectionMode="multiple"
//         copyPaste={true}
//         contextMenu={{
//           items: {
//             row_above: {},
//             row_below: {},
//             col_left: {},
//             col_right: {},
//             remove_row: {},
//             remove_col: {},
//             clear_column: {},
//             mergeCells: { name: 'Merge Cells', callback: handleMergeCells },
//             unmergeCells: {
//               name: 'Unmerge Cells',
//               callback: handleUnmergeCells,
//             },
//             set_as_date: { name: 'Set as Date', callback: handleSetAsDate },
//             set_as_currency: {
//               name: 'Set as Currency',
//               callback: handleSetAsCurrency,
//             },
//           },
//         }}
//         ref={hotTableRef}
//         afterChange={handleAfterChange}
//         persistentState={true}
//         licenseKey="non-commercial-and-evaluation"
//         manualColumnResize={false}
//         manualRowResize={false}
//         autoColumnSize={false}
//         autoRowSize={false}
//         stretchH="all"
//         mergeCells={mergeCellsConfig}
//         formulas={{ engine: hyperformulaInstance }}
//         cells={cellsHandler}
//         colWidths={DEFAULT_COLUMN_WIDTH}
//         rowHeights={DEFAULT_ROW_HEIGHT}
//       />
//     </div>
//   )
// }

// export default registerControl<Properties>(SpreadsheetControl, {
//   noDisplayLabel: true,
// })

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

import React, { useRef, useState, useEffect } from 'react'
import { HotTable } from '@handsontable/react'
import 'handsontable/dist/handsontable.full.min.css'
import Handsontable from 'handsontable'
import {
  registerControl,
  RegisterControlProps,
  RegisteredControlProperties,
} from '../hoc/registerControl'
import { CustomContentRenderer } from './utils/customButtonRenderer'
import { hyperformulaInstance, sheetId } from './utils/hyperformulaConfig'
import { reformatDate, reformatCurrency } from './utils/formatters'
import { SpreadsheetProperties } from '@components/features/FormBuilder/FormBuilderFieldProperties/Spreadsheet/types'
import { registerAllCellTypes } from 'handsontable/cellTypes'
import { registerAllPlugins } from 'handsontable/plugins'
import { useFormBuilderWorksheetGrid } from '../../hooks/useFormBuilderWorksheetGrid'
import { createSpreadsheetDefaultValue } from '../../FormBuilderFieldProperties/Spreadsheet/constants'
import { useFormBuilder } from '../../hooks/useFormBuilder'
import { useFormService } from '../../hooks/useFormService'

registerAllCellTypes()
registerAllPlugins()

type Properties = RegisteredControlProperties &
  SpreadsheetProperties & {
    externalVariables?: {
      [key: string]: {
        propertyName?: string
        defaultValue?: number
      }
    }
  }

const SpreadsheetControl: React.FC<RegisterControlProps<Properties>> = (
  props
) => {
  const hotTableRef = useRef<any>(null)
  const containerRef = useRef<HTMLDivElement>(null)

  const { rows = 1, columns = 1 } = props.properties || {}

  const DEFAULT_COLUMN_WIDTH = 100
  const DEFAULT_ROW_HEIGHT = 25

  const defaultMeta = {
    data: createSpreadsheetDefaultValue(rows, columns),
    cellFormats: {} as { [key: string]: 'date' | 'currency' | undefined },
    mergeCellsConfig: [],
  }

  const meta = props.properties?.meta || defaultMeta
  const { actions: formBuilderWorksheetActions } = useFormBuilderWorksheetGrid()
  const { actions, data: formBuilderData } = useFormBuilder()
  const { watch } = useFormService()
  const formData = watch()

  if (!actions || !actions.getAllFields) {
  }

  const [data, setData] = useState(() => JSON.parse(JSON.stringify(meta.data)))
  const [cellFormats, setCellFormats] = useState(meta.cellFormats)
  const [mergeCellsConfig, setMergeCellsConfig] = useState(
    meta.mergeCellsConfig
  )

  useEffect(() => {
    if (props.externalVariables) {
      const existingExpressions = new Set(
        hyperformulaInstance.listNamedExpressions()
      )

      Object.entries(props.externalVariables).forEach(([key, property]) => {
        const typedProperty = property as {
          propertyName?: string
          defaultValue?: number
        }

        const variableName = typedProperty.propertyName || key
        const value = Number(typedProperty.defaultValue || 0)

        if (!existingExpressions.has(variableName)) {
          try {
            hyperformulaInstance.addNamedExpression(
              variableName,
              value,
              sheetId
            )
            existingExpressions.add(variableName)
          } catch (error) {
            console.error(
              `Error adding named expression ${variableName}:`,
              error
            )
          }
        } else {
          try {
            hyperformulaInstance.changeNamedExpression(
              variableName,
              value,
              sheetId
            )
          } catch (error) {
            console.error(
              `Error updating named expression ${variableName}:`,
              error
            )
          }
        }
      })

      try {
        hyperformulaInstance.rebuildAndRecalculate()
        syncSpreadsheetWithEngine()
      } catch (error) {
        console.error(
          'Error during HyperFormula rebuild and recalculation:',
          error
        )
      }
    }
  }, [props.externalVariables])

  const syncSpreadsheetWithEngine = () => {
    if (hotTableRef.current?.hotInstance) {
      const updatedData = hyperformulaInstance.getSheetValues(sheetId)
      console.log('Syncing spreadsheet with engine. Updated Data:', updatedData)
      hotTableRef.current.hotInstance.loadData(updatedData)
    }
  }

  useEffect(() => {
    const syncSpreadsheetWithEngine = () => {
      if (hotTableRef.current?.hotInstance) {
        const updatedData = hyperformulaInstance.getSheetValues(sheetId)
        console.log(
          'Syncing spreadsheet with engine. Updated Data:',
          updatedData
        )
        hotTableRef.current.hotInstance.loadData(updatedData)
      }
    }

    if (formBuilderData) {
      const existingExpressions = hyperformulaInstance.listNamedExpressions()

      Object.entries(formBuilderData).forEach(([key, value]) => {
        const numericValue = Number(value) || 0

        if (!existingExpressions.includes(key)) {
          hyperformulaInstance.addNamedExpression(key, numericValue)
        } else {
          hyperformulaInstance.changeNamedExpression(key, numericValue)
        }
      })

      hyperformulaInstance.rebuildAndRecalculate()
      syncSpreadsheetWithEngine()
    }
  }, [formBuilderData])

  useEffect(() => {
    if (formBuilderData?.fields) {
      const existingExpressions = new Set(
        hyperformulaInstance.listNamedExpressions()
      )

      formBuilderData.fields.forEach((field) => {
        const propertyName = field.properties?.propertyName
        const defaultValue = Number(field.properties?.defaultValue || 0)

        if (propertyName && !existingExpressions.has(propertyName)) {
          try {
            hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
            existingExpressions.add(propertyName)
          } catch (error) {
            console.error(
              `Error adding named expression for ${propertyName}: ${error}`
            )
          }
        } else if (propertyName) {
          try {
            hyperformulaInstance.changeNamedExpression(
              propertyName,
              defaultValue
            )
          } catch (error) {
            console.error(
              `Error updating named expression for ${propertyName}: ${error}`
            )
          }
        }
      })

      try {
        hyperformulaInstance.rebuildAndRecalculate()
      } catch (error) {
        console.error(
          'Error during HyperFormula rebuild and recalculation:',
          error
        )
      }
    }
  }, [formBuilderData?.fields])

  useEffect(() => {
    if (formData && Object.keys(formData).length > 0) {
      const existingExpressions = hyperformulaInstance.listNamedExpressions()

      Object.entries(formData).forEach(([key, value]) => {
        if (!existingExpressions.includes(key)) {
          hyperformulaInstance.addNamedExpression(key, Number(value) || 0)
        } else {
          hyperformulaInstance.changeNamedExpression(key, Number(value) || 0)
        }
      })

      try {
        hyperformulaInstance.rebuildAndRecalculate()
      } catch (error) {}
    }
  }, [formData])

  useEffect(() => {
    const adjustedData = adjustDataDimensions(data, rows, columns)
    if (JSON.stringify(data) !== JSON.stringify(adjustedData)) {
      setData(adjustedData)
    }
  }, [rows, columns])

  const adjustDataDimensions = (
    currentData: any[][],
    rows: number,
    columns: number
  ) => {
    const newData = currentData.map((row) => [...row])
    if (newData.length < rows) {
      for (let i = newData.length; i < rows; i++) {
        newData.push(Array(columns).fill(null))
      }
    } else if (newData.length > rows) {
      newData.length = rows
    }
    newData.forEach((row) => {
      if (row.length < columns) {
        row.push(...Array(columns - row.length).fill(null))
      } else if (row.length > columns) {
        row.length = columns
      }
    })
    return newData
  }

  const handleAfterChange = (changes: any, source: string) => {
    if (!changes || source === 'loadData') return

    const validSheetId = sheetId ?? 0

    changes.forEach(([row, col, oldValue, newValue]: any) => {
      if (
        newValue &&
        typeof newValue === 'string' &&
        newValue.startsWith('=')
      ) {
        try {
          hyperformulaInstance.setCellContents(
            { sheet: validSheetId, row, col },
            [[newValue]]
          )
        } catch (error) {
          console.error('Error setting formula:', error)
        }
      }
    })

    try {
      hyperformulaInstance.rebuildAndRecalculate()
      syncSpreadsheetWithEngine() // Ensure the spreadsheet reflects changes
    } catch (error) {
      console.error('Error recalculating formulas:', error)
    }
  }

  const handleMergeCells = () => {
    const hotInstance = hotTableRef.current?.hotInstance
    const selected = hotInstance?.getSelected()
    if (selected) {
      const [startRow, startCol, endRow, endCol] = selected[0]
      const newMerge = {
        row: startRow,
        col: startCol,
        rowspan: endRow - startRow + 1,
        colspan: endCol - startCol + 1,
      }

      const updatedMergeCellsConfig = [...mergeCellsConfig, newMerge]
      hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
      setMergeCellsConfig(updatedMergeCellsConfig)

      updateFieldProperties({
        data,
        cellFormats,
        mergeCellsConfig: updatedMergeCellsConfig,
      })
    }
  }

  const handleUnmergeCells = () => {
    const hotInstance = hotTableRef.current?.hotInstance
    const selected = hotInstance?.getSelected()
    if (selected) {
      const [startRow, startCol] = selected[0]
      const mergeCellsPlugin = hotInstance.getPlugin('mergeCells')
      mergeCellsPlugin.unmerge(startRow, startCol)

      const updatedMergeCellsConfig = mergeCellsConfig.filter(
        (cell) => cell.row !== startRow || cell.col !== startCol
      )
      hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
      setMergeCellsConfig(updatedMergeCellsConfig)

      updateFieldProperties({
        data,
        cellFormats,
        mergeCellsConfig: updatedMergeCellsConfig,
      })
    }
  }

  const handleSetAsDate = () => {
    const selected = hotTableRef.current?.hotInstance.getSelected()
    if (selected) {
      const [row, col] = selected[0]
      const newFormats = { ...cellFormats, [`${row}-${col}`]: 'date' as const }
      setCellFormats(newFormats)
      updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
    }
  }

  const handleSetAsCurrency = () => {
    const selected = hotTableRef.current?.hotInstance.getSelected()
    if (selected) {
      const [row, col] = selected[0]
      const newFormats = {
        ...cellFormats,
        [`${row}-${col}`]: 'currency' as const,
      }
      setCellFormats(newFormats)
      updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
    }
  }

  const updateFieldProperties = (
    updatedMeta: Partial<SpreadsheetProperties['meta']>
  ) => {
    if (!props?.runtime) {
      const safeData = data ?? []

      formBuilderWorksheetActions?.setFieldConfigProperty(props.config?.id!, {
        meta: {
          data: [...safeData.map((row: any) => (row ? [...row] : []))],
          cellFormats: { ...cellFormats },
          mergeCellsConfig: [...mergeCellsConfig],
          ...updatedMeta,
        },
      } as Properties)
    }
  }

  const cellsHandler = (row: number, col: number) => {
    const cellProperties = {} as Handsontable.CellProperties
    cellProperties.width = DEFAULT_COLUMN_WIDTH
    cellProperties.height = DEFAULT_ROW_HEIGHT

    // Check if the cell format exists, or default to undefined
    const format = cellFormats?.[`${row}-${col}`]

    if (format === 'date') {
      cellProperties.renderer = (
        instance,
        td,
        row,
        col,
        prop,
        value,
        cellProperties
      ) =>
        CustomContentRenderer(instance, td, row, col, () => {
          const span = document.createElement('span')
          span.innerText = reformatDate(
            instance.getDataAtCell(row, col) as string
          )
          return span
        })
    } else if (format === 'currency') {
      cellProperties.renderer = (
        instance,
        td,
        row,
        col,
        prop,
        value,
        cellProperties
      ) =>
        CustomContentRenderer(instance, td, row, col, () => {
          const span = document.createElement('span')
          span.innerText = reformatCurrency(
            instance.getDataAtCell(row, col) as string
          )
          return span
        })
    }

    return cellProperties
  }

  return (
    <div
      ref={containerRef}
      className="h-[400px] w-1/2 resize-x overflow-auto border md:w-full"
      style={{ minWidth: '50%', maxWidth: '100%', resize: 'horizontal' }}
      onMouseDown={(e) => e.stopPropagation()}
    >
      <HotTable
        id="mySpreadsheet"
        data={data}
        colHeaders={true}
        rowHeaders={true}
        width="100%"
        height="100%"
        selectionMode="multiple"
        copyPaste={true}
        contextMenu={{
          items: {
            row_above: {},
            row_below: {},
            col_left: {},
            col_right: {},
            remove_row: {},
            remove_col: {},
            clear_column: {},
            mergeCells: { name: 'Merge Cells', callback: handleMergeCells },
            unmergeCells: {
              name: 'Unmerge Cells',
              callback: handleUnmergeCells,
            },
            set_as_date: { name: 'Set as Date', callback: handleSetAsDate },
            set_as_currency: {
              name: 'Set as Currency',
              callback: handleSetAsCurrency,
            },
          },
        }}
        ref={hotTableRef}
        afterChange={handleAfterChange}
        persistentState={true}
        licenseKey="non-commercial-and-evaluation"
        manualColumnResize={false}
        manualRowResize={false}
        autoColumnSize={false}
        autoRowSize={false}
        stretchH="all"
        mergeCells={mergeCellsConfig}
        formulas={{ engine: hyperformulaInstance }}
        cells={cellsHandler}
        colWidths={DEFAULT_COLUMN_WIDTH}
        rowHeights={DEFAULT_ROW_HEIGHT}
      />
    </div>
  )
}

export default registerControl<Properties>(SpreadsheetControl, {
  noDisplayLabel: true,
})
star

Sat Nov 30 2024 14:22:39 GMT+0000 (Coordinated Universal Time)

@mehran

star

Sat Nov 30 2024 10:06:55 GMT+0000 (Coordinated Universal Time) https://www.techwithtim.net/tutorials/game-development-with-python/pygame-tutorial/projectiles

@Alishure

star

Fri Nov 29 2024 21:56:33 GMT+0000 (Coordinated Universal Time)

@nofil

star

Fri Nov 29 2024 21:25:48 GMT+0000 (Coordinated Universal Time)

@gbritgs

star

Fri Nov 29 2024 18:53:42 GMT+0000 (Coordinated Universal Time)

@Joe_Devs #php

star

Fri Nov 29 2024 16:38:45 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:37:18 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:35:52 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:33:19 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:31:06 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:29:26 GMT+0000 (Coordinated Universal Time) https://github.com/Asadullah109/sigma-togather

@asadiftekhar10

star

Fri Nov 29 2024 16:29:17 GMT+0000 (Coordinated Universal Time) https://github.com/Asadullah109/sigma-togather

@asadiftekhar10

star

Fri Nov 29 2024 16:26:49 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:24:36 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 07:26:55 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 07:07:40 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 07:05:10 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 06:51:49 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 06:37:13 GMT+0000 (Coordinated Universal Time) https://www.google.com/search?q

@zipik

star

Fri Nov 29 2024 06:36:25 GMT+0000 (Coordinated Universal Time) https://www.google.com/search?q

@zipik

star

Fri Nov 29 2024 06:28:52 GMT+0000 (Coordinated Universal Time) https://miracle-garden.live/

@zipik

star

Thu Nov 28 2024 19:48:52 GMT+0000 (Coordinated Universal Time) vir pelo tik tok

@shaolin #javascript

star

Thu Nov 28 2024 15:40:56 GMT+0000 (Coordinated Universal Time)

@usman13

star

Thu Nov 28 2024 15:38:31 GMT+0000 (Coordinated Universal Time)

@RehmatAli2024 #deluge

star

Thu Nov 28 2024 15:27:23 GMT+0000 (Coordinated Universal Time)

@anamarie

star

Thu Nov 28 2024 13:45:55 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Thu Nov 28 2024 13:35:57 GMT+0000 (Coordinated Universal Time) https://creatiosoft.com/texas-holdem-poker-game-development-company

@Rishabh ##texasholdem ##pokersoftware

star

Thu Nov 28 2024 12:56:53 GMT+0000 (Coordinated Universal Time)

@odesign

star

Thu Nov 28 2024 12:44:23 GMT+0000 (Coordinated Universal Time) לא בבית כרגע אבל אני יתאר. תאורת מפתח בצד שמאל (בתמונה שלי זה הצד הימני של הפנים) של אפטור 200 וואט עם סופט בוקס בגודל של 60 ס״מ וגריד(רציתי בגודל 80 אבל יש לי מגבלה של מקום). תאורה משלימה בצד ימין (זה הצללית הקלה בצד שמאל של הפנים שלי בתמונה) של פנס לד שניתן לעמעום עם טווח של 3000- 5600 קלווין. הגדרות המצלמה - אורך מוקד מוגדר על 67, איזו על 100 ומהירות תריס 1/300 אם אני לא טועה, איזון הלבן 4800 (למרות שבמצלמה מקצועית היה נכון יותר להגדיר 5600, בבריו זה לא מדויק בעליל). תאורה אחורית חמה ויש עוד אחת בצבעי rgb שלא מופיעה בצילום

@odesign

star

Thu Nov 28 2024 10:44:22 GMT+0000 (Coordinated Universal Time) JIBAZM1u

@odesign

star

Thu Nov 28 2024 09:48:29 GMT+0000 (Coordinated Universal Time) https://algoji.com/apibridge-python-sample-code/

@pk20

star

Thu Nov 28 2024 08:14:15 GMT+0000 (Coordinated Universal Time)

@hamzahanif192

star

Thu Nov 28 2024 02:30:32 GMT+0000 (Coordinated Universal Time) /Users/khainguyen/ITRVN_REPO/BTCY/btcy-bioflux-frontend-ai_report_processing/app/LayoutV2/Reports/AiEditReport/RhythmEvents/recoil/rhythmEventsRecoilDataEffect.js

@khainguyenhm

star

Thu Nov 28 2024 02:28:57 GMT+0000 (Coordinated Universal Time) /Users/khainguyen/ITRVN_REPO/BTCY/btcy-bioflux-frontend-ai_report_processing/app/LayoutV2/Reports/AiEditReport/BeatHR/recoil/beatHrRecoilDataEffect.js

@khainguyenhm

star

Thu Nov 28 2024 02:27:42 GMT+0000 (Coordinated Universal Time)

@khainguyenhm

star

Thu Nov 28 2024 01:48:36 GMT+0000 (Coordinated Universal Time) https://gist.github.com/victorzen/c5aae1a5880fe2be79a92776ee040d7a

@D_Unbounce

star

Wed Nov 27 2024 21:26:25 GMT+0000 (Coordinated Universal Time)

@E23CSEU1151

star

Wed Nov 27 2024 20:55:24 GMT+0000 (Coordinated Universal Time)

@nachopascual #php

star

Wed Nov 27 2024 20:37:53 GMT+0000 (Coordinated Universal Time)

@desiboli #javascript #typescript

star

Wed Nov 27 2024 20:26:06 GMT+0000 (Coordinated Universal Time)

@E23CSEU1151

star

Wed Nov 27 2024 19:53:07 GMT+0000 (Coordinated Universal Time)

@okkpurple

star

Wed Nov 27 2024 17:38:58 GMT+0000 (Coordinated Universal Time)

@shusanto

star

Wed Nov 27 2024 15:54:20 GMT+0000 (Coordinated Universal Time) https://www.youtube.com/watch?v

@abcabcabc

star

Wed Nov 27 2024 13:06:53 GMT+0000 (Coordinated Universal Time) https://learn.upgrad.com/course/6955/segment/55858/338400/1023321/5117004

@dorjee

star

Wed Nov 27 2024 13:05:27 GMT+0000 (Coordinated Universal Time)

@odesign

star

Wed Nov 27 2024 11:46:09 GMT+0000 (Coordinated Universal Time)

@anamarie

star

Wed Nov 27 2024 06:49:36 GMT+0000 (Coordinated Universal Time) https://www.coinsclone.com/nft-sports-marketplace-development/

@LilianAnderson #nftsportsmarketplace #sportsnfts #nftmarketplacedevelopment #blockchaininsports #sportscollectiblesnft

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension