How do i upload an image and some texts in NextJS

How do I upload image and text in next.js API route ? I have front end ready. here is the onSubmit function for uploading image and text. please point out what I’m doing wrong here.
Can someone help and possibly explain this to me so I can make sense of it for future reference.

Thanks

async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();

    const res = await fetch("/api/articles", {
      method: "POST",
      body: JSON.stringify({ formData }),
      headers: { "content-type": "application/json" },
    });

    if (!res.ok) {
      throw new Error("failed to create ticket.");
    }

    router.refresh();
    router.push("/");
  } 

this is the Api endpoint

import Post from "@/app/(model)/post";
import { writeFile } from "fs/promises";
import { NextRequest, NextResponse } from "next/server";
import { join } from "path";


export async function POST(req:NextRequest, data: FormData) {
  'use server'
console.log('post created')
  try {
    const body = await req.json()
    const file: File | null = data.get("file") as unknown as File;
    if (!file) {
      throw new Error("No file uploaded");
    }
    const postData = body.formData
    const bytes = await file.arrayBuffer();
    const buffer = Buffer.from(bytes);
    const path = join('/', 'tmp', file.name)
    await Post.create(postData)
    await writeFile(path, buffer)
    return NextResponse.json({message: 'Post Created'}, {status: 201})

  } catch (error) {
    return NextResponse.json({message: 'Error', error}, {status: 500})
  }
  }
  
  

Issue copying files from one library to another in SPO using no framework spfx

I need your help. I am trying to copy a file from Documents1 library to Document2 library in sharepoint online using the code below but I am getting “403 forbidden-The security validation for this page is invalid and might be corrupted. please use your web browser’s Back button to try your operation again.”. What am I doing wrong? I am using spfx using no framework. Any suggestions? Any better solution using no framework?

private copyDocumentAndUpdateMetadata(List: any, documentName:any,ID: number):void { 

    const metadata = {
      'Title': 'Test'
  };
    // Step 1: Retrieve the source document and its metadata 
    fetch(this.context.pageContext.web.absoluteUrl + "/_api/web/lists/GetByTitle('Documents1')/Items("+ ID + ")?$select=*,FileLeafRef,Editor/Name,Editor/Title,File/ServerRelativeUrl&$expand=Editor/Id,File", {
        method: 'GET',
        headers: {
            'Accept': 'application/json; odata=verbose'
        }
    }).
        then(response => response.json())
        .then(data => {
            // Extract source document properties 
            //const etag = data.d.__metadata.etag;
            const fileBuffer = data.d.File.ServerRelativeUrl;
            //const sourceItemId = data.d.ListItemAllFields.Id;
            // Step 2: Upload the document to the destination library 
            fetch(this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getByTitle('" + List +"')/rootfolder/Files/add(url='" + documentName + "',overwrite=true)", {
                method: 'POST',
                headers: {
                    'Accept': 'application/json; odata=verbose',
                    'Content-Type': 'application/json; odata=verbose',
                    'odata-version': ''
                },
                body: fileBuffer
            })
                .then(response => response.json())
                .then(data => {
                    // Step 3: Update metadata in the destination library 
                    fetch(this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getbytitle('" + List +"')/items(" + data.d.ID + ")", {
                        method: 'POST',
                        headers: {
                            'Accept': 'application/json;odata=verbose',
                            'Content-Type': 'application/json;odata=verbose',
                            'odata-version': '',
                            'IF-MATCH': '*',
                            'X-HTTP-Method': 'MERGE'
                            
                        },
                        body: JSON.stringify(metadata)
                    })
                        .then(response => {
                            console.log("Document copied and metadata updated successfully");
                        })
                        .catch(error => {
                            console.error('Error updating metadata:', error);
                        });
                })
                .catch(error => {
                    console.error('Error uploading document:', error);
                });
        })
        .catch(error => {
            console.error('Error retrieving source document:', error);
        });
}

Hide load more button and if no more post in WordPress

I have built a ajax post loading program in wordpress where i load post depending on category and current post type.

ive got it all working except hiding the load more button if no more post.

ive been at this for weeks and can not figure it out, can some one help me finish this project.

All i need is for the total post to be dynamic so i can hide the Load more if no more to load.

Thank you

I was flowing https://joeyfarruggio.com/wordpress/skeleton-loader/

Code

<html>
<head>
   <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
     <script>
document.addEventListener('alpine:init', () => {
    
        attrs = $( 'body' ).attr( 'class' ).split( ' ' );
        jQuery( attrs ).each(function() {

            if ( 'post-type-' === this.substr( 0, 10 ) ) {
                postType = this.split( 'post-type-' );
                postType = postType[ postType.length - 1 ];
                return;
            }
        });
        
        postType = postType.replace('archive-', '');
    
    var post_id = postType;
    

Alpine.data("filterPosts", (adminURL) => ({
    posts: "",
    limit: 6,
    category: null,
    post_type_js: post_id,
    showDefault: true,
    showFiltered: false,
    offset: 0,
    total:0,
    
    filterPosts(id) {
        this.showDefault = false;
        this.showFiltered = true;
        this.category = id;
        this.offset = 0; // <-- reset offset to zero
        this.total = 0;
        this.fetchPosts();
    },
    
    loadMore() {
        this.loadingMore = true;
        this.total = 0;
        this.offset += 6;
        this.showFiltered = true;
        this.fetchPosts(true);
    },

    fetchPosts(append = false) {
        var formData = new FormData();
        formData.append("action", "filterPosts");
        formData.append("limit", this.limit);
        formData.append("post_type_js", this.post_type_js);
        formData.append("offset", this.offset); 

        if (this.category) {
            formData.append("category", this.category);
            formData.append("total", this.total);
        }

    fetch(adminURL, {
        method: "POST",
        body: formData,
    })
    .then((res) => res.json())
    .then((res) => {
            if (append) {
                // Appends posts to the end of existing posts data
                this.posts = this.posts.concat(res.posts);
            } else {
                // Resets the posts data with new data
                this.posts = res.posts;
            }

            this.loading = false;
        });
    },
    
    getTotal() {
    var formData = new FormData();
    formData.append("action", "filterPosts");

    fetch(adminURL, {
        method: "POST",
        body: formData,
    })
    .then((res) => res.json())
    .then((res) => {
        this.total = res.total;
    });
},

init() {
    this.getTotal();
}

}));
})




let activeElement = document.querySelector('.active');
let numberOfPosts = activeElement ? activeElement.textContent.replace(/[^0-9]/g, '') : 0;
        
  console.log("post count is", numberOfPosts );
     </script>
     

     
   
</head>
<body>
    <div x-data="filterPosts('<?php echo admin_url('admin-ajax.php'); ?>')">
<section <?php theme_section_attr_id() ?> <?php theme_section_attr_class('main-section js-posts') ?>>
  <div class="container">
    <div class="heading text-md-center">
      <?php $before_title = get_sub_field('before_title');
      if ($before_title) : ?>
        <strong class="sub-title"><?php echo $before_title ?></strong>
        
      
      <?php endif ?>
      <?php $title = get_sub_field('title');
      if ($title) : ?>
        <h2><?php echo $title ?> </h2>
      <?php endif ?>
    </div>

      <div class="head js-posts-search-text">
        <?php if ($search_value) : ?>
          <h2 class="h5 fw-semibold"><?php printf(__('Showing results for “%s”', 'base'), $search_value) ?></h2>
        
        <?php endif ?>
      </div>
      
<!--alipne js dynamic post start-->
    <div class="has-filter row flex-md-row-reverse">
          <!-- Posts Column -->
        <div class="col-md-8 col-lg-9 js-posts-holder">
            
            
           <!-- Default posts query -->
            <div x-show.important="showDefault" class="row cards-area js-posts-items pb-4">
                <?php get_template_part( 'template-parts/posts-filter/default-query' ); ?>
            </div>
                <!-- Filtered posts -->
            <div x-show.important="showFiltered" class="row cards-area js-posts-items" x-html="posts">
                 
            </div>
            <!-- Load More Posts -->
            
              <!-- Load More Posts -->
            <div @click="loadMore()" x-show="total > (limit + offset)" class="text-center pt-4">
                 <button class="border border-solid border-slate-700 text-slate-100 hover:bg-slate-800 px-4 py-2"> Load More </button>
            </div>
         </div>
            
        <!-- Filtered posts -->
        <div class="col-md-4 col-lg-3">
             <?php get_template_part( 'template-parts/posts-filter/filter-query' ); ?>
        <!-- Filtered end -->
         </div>   
    </div>
    </div>
<!--alipne js dynamic post end-->

</section>
</div>
</body>
</html>

Ajax

    <?php // the ajax function
add_action('wp_ajax_filterPosts', 'filterPosts');
add_action('wp_ajax_nopriv_filterPosts', 'filterPosts');

function filterPosts()
{
    $response = [
        'posts' => "",
    ];
    
    $all_args = array(
        'posts_per_page' => -1, // returns all posts
        'post_status' => 'publish',
    );
    
    $filter_args = array(
        'post_status' => 'publish',
    );
    
     if ($_POST['limit']) {
        $filter_args['posts_per_page'] = max (0, (int) $_POST['limit']);
    }
    
    if (isset($_POST['offset'])) {                      
        $filter_args['offset'] = max (0, (int)$_POST['offset']);
    }

     if ($_POST['post_type_js']) {
        $filter_args['post_type'] = $_POST['post_type_js'];
    }

    if ($_POST['category']) {
        $filter_args['cat'] = $_POST['category'];
        
        // Get the total number of posts for the category
        $filter_args['paged'] = $_POST['total'];
       
    }

    $filter_query = new WP_Query($filter_args);

    if ($filter_query->have_posts()) :
        while ($filter_query->have_posts()) : $filter_query->the_post();
            $response['posts'] .= load_template_part('/template-parts/posts-filter/single-post');
        endwhile;
        wp_reset_postdata();
    endif;

    echo json_encode($response);
    die();
}

Sidebar for category selection

 <style>
      a.child {
              margin-left: 10px;
      }
      
      ul.filter-list a.active {
        font-weight: 700;
        border-bottom: none;
}


ul.filter-list a:hover {
  
    border-bottom: 3px solid #4ef4cb !important;
}


  </style>
  <script>
      
        attrs = $( 'body' ).attr( 'class' ).split( ' ' );
        jQuery( attrs ).each(function() {

            if ( 'post-type-' === this.substr( 0, 10 ) ) {
                postType = this.split( 'post-type-' );
                postType = postType[ postType.length - 1 ];
                return;
            }

        });
        
        postType = postType.replace('archive-', '');
        
    var post_id = postType;


  </script>
  <aside class="sidebar">
                 <div class="widget widget-filter">
                     <button class="widget-title">Explore Topics</button>
                     <svg class="separator" viewBox="0 0 238 11" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
                <line opacity="0.3" y1="0.5" x2="101.942" y2="0.5" stroke="#3CD5AF"></line>
                <line opacity="0.3" y1="10.5" x2="237.5" y2="10.5" stroke="#3CD5AF"></line>
              </svg>
<?php


$string = basename($wp->request); ;
$string = str_replace('-', '_', $string);

$new_string = $string;
// echo $new_string;

 $args = array(
                    'post_type'      => $new_string,
                    'post_status'    => 'publish',
                );

    $the_query = new WP_Query( $args );
    $my_categories = array();
    if ( $the_query->have_posts() ) {
        while ( $the_query->have_posts() ) {
            $the_query->the_post();
               $postType = get_queried_object();

            $terms = get_the_terms( get_the_ID(), 'category' );
            if ( $terms && ! is_wp_error( $terms ) ) : 
                foreach ( $terms as $term ) {
                if(!in_array($term->term_id, $my_categories))
                    $my_categories[] = $term->term_id;
                }   
            endif;  
        }
        wp_reset_postdata();
    }

    if(sizeof($my_categories)) { ?>

     <ul class="filter-list">
             <li :class="category == 0 ? 'parent' : ''" ;>
      <a class="" @click="filterPosts">Show All</a>
      
      <?php
 


$args = array(
  'cat' => $category_id,
  'post_type' => $new_string,
);

 
?>
      </li>
      
  
         <?php foreach ($my_categories as $term_id) {
            $category = get_term_by('id', $term_id, 'category');
        
            if($category->slug!="all-articles") {
                if($category->parent != 0){ // If this is a subcategory

$args = array(
    'numberposts' => -1,
    'category' => $category->term_id,
    'post_type' => $new_string,
);
$count_posts = get_posts( $args );
$total_posts_child = count($count_posts);


  ?>
          <li :class="category == <?php echo $category->term_id; ?> ? 'child' : ''" ;>
                     <a class="child" @click="filterPosts(<?= $category->term_id; ?>)"><?= esc_html( $category->name ); echo " ". "(" .$total_posts_child . ")"; ?></a>
                </li> <?php
    
    } else {
   
                
                $args = array(
    'numberposts' => -1,
    'category' => $category->term_id,
    'post_type' => $new_string,
);
$count_posts = get_posts( $args );
$total_posts_parent = count($count_posts);

 ?>
      <li :class="category == <?php echo $category->term_id; ?> ? 'parent' : ''" ;>
                     <a class="parent" @click="filterPosts(<?= $category->term_id; ?>)"><?= esc_html( $category->name); echo " ". "(" .$total_posts_parent . ")" ?></a>
                </li>   <?php
    }
          
            }
        }
    }
    ?>
    </ul>
 
    </div>
    </aside>

Add multiple toast notification and each one has it’s own disappearance time with javascript

I’m a student and it’s my first time here !
So I’m trying to code a toast notification for the first time, here’s mine : toast notification
The problem is, when I add several of them, after 5s, they go below everything. I wanted it to be like this but after they all disappeared. And I don’t know how to add like a personal disappearance time to each of the toast notification. So when one disappears, the others are like that : problematic toast notifications
The container has to disappear because either way I can’t click on the button add to cart that are below it.
Do you have an idea for how to fix this ? If you have any code advice too, don’t hesitate to tell me !

Here’s the code (a little chaotic because I tried to follow youtube videos and then add my own thing and then I tried to find a solution with Gemini (Google AI) so yeah… ) :

HTML

<div class="container-alert">
     <div class="alert hide">
          <svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" viewBox="0 0 48 48">
               <defs>
                    <mask id="ipSCheckOne0">
                        <g fill="none" stroke-linejoin="round" stroke-width="4">
                            <path fill="#fff" stroke="#fff" d="M24 44a19.937 19.937 0 0 0 14.142-5.858A19.937 19.937 0 0 0 44 24a19.938 19.938 0 0 0-5.858-14.142A19.937 19.937 0 0 0 24 4A19.938 19.938 0 0 0 9.858 9.858A19.938 19.938 0 0 0 4 24a19.937 19.937 0 0 0 5.858 14.142A19.938 19.938 0 0 0 24 44Z"/>
                            <path stroke="#000" stroke-linecap="round" d="m16 24l6 6l12-12"/>
                        </g>
                    </mask>
               </defs>
               <path fill="#30d300" d="M0 0h48v48H0z" mask="url(#ipSCheckOne0)"/>
           </svg>
                
           <span class="msg"></span>

           <div class="close-btn">
                <span class="fas fa-times"></span>
           </div>
     </div>
</div>

CSS

.container-alert {
    width: 30rem;
    position: fixed;
    right: 0;
    bottom: 0px;
    display: flex;
    align-items: center;
    justify-content: end;
    flex-direction: column;
    overflow: hidden;
    padding: 20px;
    z-index: -1;
}


.alert {
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    width: 27rem;
    height: 5rem;
    font-weight: 500;
    box-shadow: 0 0 20px rgba(0,0,0,0.3);
    display: flex;
    align-items: center;
}

.alert.showAlert {
    opacity: 1;
    pointer-events: auto;
    background-color: #fff;

}

JavaSript

function toastNotification(msg) {
    const alertContainer = document.querySelector(".container-alert"); // Select the container
    const newAlert = document.createElement("div"); // Create a new alert element
    newAlert.classList.add("alert", "showAlert"); // Add necessary classes
    ...
    const closeBtn = document.createElement("div");
    closeBtn.classList.add("close-btn");
    const closeIcon = document.createElement("i");
    closeIcon.classList.add("fas", "fa-times");
    closeBtn.appendChild(closeIcon);
    newAlert.appendChild(closeBtn);

    // Append the new alert to the container
    alertContainer.appendChild(newAlert);

    // Add animation for showing and hiding the alert
    newAlert.classList.add("show");

    alertContainer.style.zIndex = "9999";

    setTimeout(() => {
        newAlert.classList.remove("show");
        newAlert.classList.add("hide");

        // Remove the alert after hiding animation
        setTimeout(() => {
            alertContainer.removeChild(newAlert);
            alertContainer.style.zIndex = "-1";
        }, 5000);
    }, 5000);


    

    closeBtn.addEventListener("click", () => {
        newAlert.classList.remove("show");
        newAlert.classList.add("hide");

        // Immediately remove the alert if closed manually
        setTimeout(() => {
            alertContainer.removeChild(newAlert);
            alertContainer.style.zIndex = "-1";
        }, 5000);

    });
}

Insert rows into MYSQL from dynamic PHP rows [duplicate]

I created a form with dynamic rows in PHP. My problem is that I cannot insert the form data to mysql.

I have a page with apparatus’s listed with an edit button. When you click the edit button, It pulls up the form with dynamic row adding so the user can create their own checklist. When the user is done and clicks submit, It should insert that data to the correct table in the database.

This is the dynamic form:

<?php

@include 'config.php';

if (isset($_GET['id'])){ 
    
    $appid = $_GET['id']; 
  
$sqlapp = " SELECT apparatus FROM truck_check WHERE id = '$appid' ";
    
$resultappfetch = mysqli_query($conn,$sqlapp);
    
$appfetch = mysqli_fetch_assoc($resultappfetch);

$appname = $appfetch['apparatus'];

    }  



?>

<!DOCTYPE html>

<html>
    <head>
        <title>Truck Check</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    </head>
    <body>
        <div class="container">
            <br />
            <br />
            <h2 align="center"><?php echo $appname?></h2><br />
            <div class="form-group">
                <form name="add_name" id="add_name">
                    <div class="table-responsive">
                        <table class="table table-bordered" id="dynamic_field">
                            <tr>
                                <td><input type="text" name="name[]" placeholder="Enter Check" class="form-control name_list" /></td>
                            </tr>
                        </table>
                        
                                <td><button type="button" name="add" id="add" class="btn btn-success">Add Check</button></td>
                        <input type="button" name="submit" id="submit" class="btn btn-info" value="Submit" />
                    </div>
                </form>
            </div>
        </div>
    </body>
</html>

<script>
$(document).ready(function(){
    var i=1;
    $('#add').click(function(){
        i++;
        $('#dynamic_field').append('<tr id="row'+i+'"><td><input type="text" name="name[]" placeholder="Enter Check" class="form-control name_list" /></td><td><button type="button" name="remove" id="'+i+'" class="btn btn-danger btn_remove">X</button></td></tr>');
    });
    
    $(document).on('click', '.btn_remove', function(){
        var button_id = $(this).attr("id"); 
        $('#row'+button_id+'').remove();
    });
    
    $('#submit').click(function(){      
        $.ajax({
            url:"editcheckpub.php",
            method:"POST",
            data:$('#add_name').serialize(),
            success:function(data)
            {
                alert(data);
                $('#add_name')[0].reset();
            }
        });
    });
    
});
</script>

This is the ajax call php:

<?php

@include 'config.php';

$number = count($_POST["name"]);
if($number > 1)
{
    for($i=0; $i<$number; $i++)
    {
        if(trim($_POST["name"][$i] != ''))
        {
            $sql = "INSERT INTO $appname(name) VALUES('".mysqli_real_escape_string($conn, $_POST["name"][$i])."')";
            mysqli_query($conn, $sql);
        }
    }
    echo "Data Inserted";
}
else
{
    echo "Please Enter Name";
}

?>

Display x amount left until discount – liquid Shopify

I want to show a message how much client needs to spend more until he gets additional discount.
I have 4 discounts setup in shopify discounts.
2% off entire order • Minimum purchase of €81.00
3% off entire order • Minimum purchase of €61.00
2% off entire order • Minimum purchase of €41.00
5% off entire order • Minimum purchase of €20.00

   {% assign cart_total = cart.total_price | divided_by: 100 %}
   {% assign discount1_threshold = 81 %}
   {% assign discount2_threshold = 61 %}
   {% assign discount3_threshold = 41 %}
   {% assign discount4_threshold = 20 %}

   {% if cart_total < discount4_threshold %}
    Amount until 5% discount {{ discount4_threshold | minus: cart_total }}€
   {% elsif cart_total < discount3_threshold %}
    Amount until 2% discount {{ discount3_threshold | minus: cart_total }}€
   {% elsif cart_total < discount2_threshold %}
    Amount until 3% discount {{ discount2_threshold | minus: cart_total }}€
   {% elsif cart_total < discount1_threshold %}
    Amount until 2% discount {{ discount1_threshold | minus: cart_total }}€
   {% else %}
    Congrats! You've reached maximum discount value.
   {% endif %}

So I managed to achieve this behaviour with liquid in shopify ( I want it to show in side cart )

However, it needs to be refreshed everytime you add to cart to update the message. I’ve tried using JS but sadly couldn’t make it work. How do I make it happen?
Any help or tips appreciated.

I’ve tried using JS but sadly couldn’t make it work.

Text Transition Animation Isn’t Working Properly, Is Glitching Instead

Currently this text animation function is producing a glitching effect upon manually resizing the screen.. Meaning it only transitions through each word when you shrink or expand the screen..

function animateText() {
        const $lastElement = $element.last(0);
        const $text = $lastElement.find('.js__text' , '.js__svg');
        const words = ['apart', 'out', 'shine']; // Array of words to animate

        let currentIndex = 0;

        setInterval(() => {
            $text.fadeOut(400, function() {
                $(this).text(words[currentIndex]);
            }).fadeIn(400);

            currentIndex = (currentIndex + 1) % words.length;
        }, 2000);
    }


    // Automatically trigger the animation on page load
    $window.on('load', function() {
        animateText();
    });
}

Can anyone pinpoint what I’ve done wrong?

VS-code prettier extension removing perentheses

hello guys i need help with my code when i add perentheses prettier keeps on removing them, i did a little research and added .prettierrc in my root directory with the folloing:

 {
    "bracketSpacing": true,
    "jsxBracketSameLine": false,
    "singleQuote": true,
    "trailingComma": "all",
    "arrowParens": "always",
    "removeParens": false
     }

i am trying to add perentheses around my operation but it is not letting me

const modulo = (a, b) => {
  return ((a * 10) % (b * 10)) / 10;
};
const divide = (a, b) => {
  return (a * 10) / (b * 10) / 10;
};
const multiply = (a, b) => {
  return (a * 10 * (b * 10)) / 100;
};
const subtraction = (a, b) => {
  return (a * 10 - b * 10) / 10;
};
const addition = (a, b) => {
  return (a * 10 + b * 10) / 10;
};

any help???
i tried to add perentheses around my functions but prettier isnt allowing me, for some reason it is allowing my first function to work but not other function

style of semaphore usage on execution order between the different instructions of P1 and P2

Considering two processes P1 and P2. If we wanted to define an execution order between the different instructions of P1 and P2, then which style of semaphore usage you would apply?

Mutual exclusion style.
Waiting style.

Considering two processes P1 and P2. If we wanted to define an execution order between the different instructions of P1 and P2, then which style of semaphore usage you would apply
such that :
the difference between them lies in their focus:

Mutual Exclusion Style: Primarily concerned with ensuring that only one process can execute a critical section at a time to prevent conflicts.

Waiting Style: Primarily concerned with coordinating the order of execution between processes or threads, often involving waiting for specific conditions or signals before proceeding.

How to initialize a object with values in component Angular?

I’m trying to initialize my object with values that comes from my backend.
So on ngOninit I can bring my data values from service, but I’m don’t know how to Initialize this object from component with this values. I need this values to show in a select from template, so this values has to initialize when the template renderize.

Object
ngOnInit
select from template
console.log from ngOnInit of component

I tried to change the types from model but it’s not works. When I mock this datas it’s work.

How to avoid integrity constraint violations from duplicate sql insert commands triggered by >= async api calls at the same time in Laravel?

Our react app triggering X amount of same async requests (with different inputs) to our Laravel GraphQL API to avoid slow performance and improve fault tolerance.

Sometimes they insert into the same intermediate table with the same values, even with checks to see if the value doesn’t already exist before inserting.

My guess is that Laravel is allowing N amount of async calls to insert into the intermediate table at the same time after they both bypass the check to see if the record already exists.

Then this throws an Integrity Constraint error due to a duplicate value and errors out.

Other than sending each request sequentially (which we are doing now but is slower) or queueing jobs to perform the inserts (which is more complicated), are there any other ways to make sure that MySQL doesn’t run those 2 queries at the same time?

I have read that upserting or using a try catch can mask the error, but still doesn’t solve the core problem.

Here is the code that is triggered multiple times and throwing the error.

I rewrote the code to not use sync or syncWithoutDetaching because they were both throwing the error more frequently.

    /**
     * Add strategy_department record, if that key does not already exist
     *
     * @param Strategy $strategy
     * @param Task $task
     *
     */
    private function addStrategyDepartmentIfDoesntExist(Strategy $strategy, Task $task): void
    {
        $this->handleErrorsForAddStrategyDepartmentIfDoesntExist($strategy, $task);
        $strategy_department_table_name = 'strategy_department';

        /**
         * If error is not thrown, then we can add the department to the strategy if it doesn't exist
         */
        $strategy_department_found = DB::table($strategy_department_table_name)
            ->where('strategy_id', $strategy->id)
            ->where('department_id', $task->service->department->id)->first();

        if (!isset($strategy_department_found)) {
            DB::table($strategy_department_table_name)->insert([
                'strategy_id' => $strategy->id,
                'department_id' => $task->service->department->id,
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }
    }

Merge all excel sheets into a one new Sheet

I need your help, I have an Excel file type .xlsx, which was sent automatically from a system to my email, this Excel comes with the information distributed in several tabs within the same file, what I want to do is an Office script that takes the information from each of the sheets and unifies it into a single sheet, once all the data has been copied, delete all the sheets and the file is left with a single tab, with all the data unified. Thanks for your help.

function main(workbook: ExcelScript.Workbook) {
  // Get all the worksheets in the workbook
  let sheets = workbook.getWorksheets();

  // Create a new worksheet named "Consolidate"
  let consolidateSheet = workbook.getWorksheet("Consolidate") || workbook.addWorksheet("Consolidate");

  // Loop through each sheet in the workbook
  for (let sheet of sheets) {
    // Get the data range of the current sheet
    let dataRange = sheet.getUsedRange();

    // Get the values from the data range
    let values = dataRange.getValues();

    // Find the last row with data in the Consolidate sheet
    let lastRow = consolidateSheet.getUsedRange().getRowCount();

    // Get the range where the data will be pasted in the Consolidate sheet
    let targetRange = consolidateSheet.getRange(lastRow + 1, 1, values.length, values[0].length);

    // Paste the values into the Consolidate sheet
    targetRange.setValues(values);
  }
}

vitest react write-excel-file: how to test FileSaver.saveAs (download file)

i try to write a test for my react component that displays a button, and when clicked generates a xlsx file and offers to download.
for this i use these tools:

for this i found
How to use Jest to test file download?

and tried to translate this jest example to my vitest enviroment:

// ...
import FileSaver from "file-saver";
vi.mock("file-saver", () => {
  return {
    default: { saveAs: vi.fn() },
    saveAs: vi.fn(),
  };
});

global.Blob = function (content, options) {
  return { content, options };
};

// ...

but i get

FAIL  src/MyExample/index.test.jsx > MyExample > check template download AssertionError: 
expected "spy" to be called at least once  ❯ src/MyExample/index.test.jsx:29:30
     27|     await user.click(btn);
     28| 
     29|     expect(FileSaver.saveAs).toHaveBeenCalled();
       |                              ^
     30|     expect(FileSaver.saveAs).toHaveBeenCalledWith(
     31|       {

i have no idea if my basic concept can work at all..
i thought that with this mock i replace the global FileSaver lib..
but it seems this is not the case..
i am a bit lost how to track this done and would like to learn too..
i already extracted the saveAs part from the write-excel-file library to my own component so that it is a bit easier for me to understand what is going on..
without success currently.

What is the correct way / best practice to setup such a test case?

my full example at codesandbox.io

my component looks like this

import * as React from "react";
import { Button } from "@mui/material";

import writeXlsxFile from "write-excel-file";

export const MyExample = () => {
    const exampleData = [
        {
            forename: "Diana",
            surname: "Umlauft",
            email: "[email protected]",
        },
        {
            forename: "Jana",
            surname: "Friedmann",
            email: "[email protected]",
        },
    ];

    const columnsDefinition = [
        {
            column: "forename",
            value: (person) => person.forename,
            type: String,
            width: 15,
        },
        {
            column: "surname",
            value: (person) => person.surname,
            type: String,
            width: 15,
        },
        {
            column: "email",
            value: (person) => person.email,
            type: String,
            width: 30,
        },
    ];

    async function handleDownloadExampleXLSX(event) {
        console.log("handleDownloadExampleXLSX");
        try {
            const xlsxBlob = await writeXlsxFile(exampleData, {
                schema: columnsDefinition,
                // https://gitlab.com/catamphetamine/write-excel-file#browser
                // when no fileName is given results in blob
                fileName: `testFile.xlsx`,
            });
            //console.log("xlsxBlob", xlsxBlob);
            // saveAs(xlsxBlob, `testFile.xlsx`);
        } catch (error) {
            console.log(error);
        }
    }

    return (
        <>
            <Button onClick={handleDownloadExampleXLSX}>
                Download Example
            </Button>
        </>
    );
};

export default MyExample;

and my test file

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import MyExample from ".";

// based on https://stackoverflow.com/questions/44686077/how-to-use-jest-to-test-file-download
import FileSaver from "file-saver";
vi.mock("file-saver", () => {
  return {
    default: { saveAs: vi.fn() },
    saveAs: vi.fn(),
  };
});

global.Blob = function (content, options) {
  return { content, options };
};

describe("MyExample", () => {
  test("check template download", async () => {
    const user = userEvent.setup();
    const { container } = render(<MyExample />);
    const btn = screen.getByText(/Download/i, {
      selector: "button",
    });
    expect(btn).toBeInTheDocument();
    await user.click(btn);

    expect(FileSaver.saveAs).toHaveBeenCalled();
    expect(FileSaver.saveAs).toHaveBeenCalledWith(
      {
        size: 5531,
        options: {
          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        },
      },
      "testFile.xlsx",
    );
  });
});

Javascript: Date string in different locale to Timestamp

I have a time string that I need to convert into a timestamp, but it’s in the timezone of another location. The location uses DST, so it isn’t as simple as adding some constant offset.
For example, I want to go from
Mar 10, 2024, 06:00:00 (America/Vancouver time)
to
1710075600000.

Date.parse works fine if the user is actually in America/Vancouver, but produces different timestamps if they’re in Portugal.

I tried adding the target timezone to the date string, but I wasn’t accounting for DST.
Date.parse('Mar 10, 2024, 06:00:00 PST') produces 1710079200000. I should use PDT in this case, but I’m not sure how to check if a future date is in DST in a different timezone.

How to Call Vue component inside React Micro Frontend using WebPack 5

I have started to learn micro frontend. First, I have create a react mf project Micro-Shell-App using npx create-mf-app. Second, I have created again vue mf project that is named SectionPart using same npx code. I want to share an any vue component with react shell app. How can I do it ? I am trying something but i did not find a solution. I am facing error like:

Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: object.

Do you have any advice to me? Thanks from now.

Here is folder structure:

enter image description here

MyComponent.vue:

<template>
  <div>
    <h2>Hello, {{ name }}!</h2>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: 'World'
    };
  }
};
</script>

SectionPart webpack.config.js:

// some imports
module.exports = (_, argv) => ({
  output: {
    publicPath: "http://localhost:3003/",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".vue", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3003,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /.vue$/,
        loader: "vue-loader",
      },
      {
        test: /.tsx?$/,
        use: [
          "babel-loader",
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true,
              appendTsSuffixTo: ["\.vue$"],
              happyPackMode: true,
            },
          },
        ],
      },
      {
        test: /.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
    ],
  },

  plugins: [
    new VueLoaderPlugin(),
    new ModuleFederationPlugin({
      name: "SectionPart",
      filename: "remoteEntry.js",
      remotes: {
       
      },
      exposes: {
        "./MyComponent":"./src/components/MyComponent.vue",
      },
      shared: require("./package.json").dependencies,
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
    new Dotenv()
  ],
});

Micro Shell App webpack.config.js:

// some imports 

module.exports = (_, argv) => ({
  output: {
    publicPath: "http://localhost:3000/",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3000,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /.vue$/,
        loader: "vue-loader",
        exclude: /node_modules/
    }
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "Micro_Shell_App",
      filename: "remoteEntry.js",
      remotes: {
        section:"SectionPart@http://localhost:3003/remoteEntry.js"
      },
      exposes: {},
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
    new VueLoaderPlugin(),
    new Dotenv()
  ],
});

App.jsx at Shell:

import React from "react";
import ReactDOM from "react-dom";
import MyComponent from "section/MyComponent"

const App = () => (
 
    <MyComponent />
  
);
ReactDOM.render(<App />, document.getElementById("app"));