<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Haruka Kakiuchi</title>
    <description>The latest articles on Forem by Haruka Kakiuchi (@kakimaru).</description>
    <link>https://forem.com/kakimaru</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1460099%2F4a222210-86e5-4e91-bcbc-9889e6bda81f.png</url>
      <title>Forem: Haruka Kakiuchi</title>
      <link>https://forem.com/kakimaru</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kakimaru"/>
    <language>en</language>
    <item>
      <title>We Built a Birthday Party Planner App in 4 Weeks with Next.js – Here’s What We Learned</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Wed, 16 Apr 2025 20:54:28 +0000</pubDate>
      <link>https://forem.com/kakimaru/i-built-a-birthday-party-planner-app-with-nextjs-2gpo</link>
      <guid>https://forem.com/kakimaru/i-built-a-birthday-party-planner-app-with-nextjs-2gpo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi, I’m Haruka — a UI designer with 4 years of experience!&lt;br&gt;
I’m currently studying Web Development at a community college in Vancouver, working as a co-op student.&lt;/p&gt;

&lt;p&gt;In this article, I’ll talk about a web app I made as my final school project. I’ll share how we built it and what I learned from working in a team.&lt;/p&gt;

&lt;p&gt;I hope this helps anyone who wants to try making their own web service or join a hackathon!&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Team Members
&lt;/h3&gt;

&lt;p&gt;We had 4 people:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 backend developers (1 was also the project manager)&lt;/li&gt;
&lt;li&gt;2 frontend/designers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our PM had experience in web backend. One backend and one frontend had embedded systems experience. I had some HTML/CSS experience.&lt;/p&gt;
&lt;h3&gt;
  
  
  Project Length
&lt;/h3&gt;

&lt;p&gt;4 weeks of coding(2 weeks to prepare for the final demo presentation)&lt;/p&gt;
&lt;h3&gt;
  
  
  My Role
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;UI/UX planning&lt;/li&gt;
&lt;li&gt;Wireframes, prototypes, and design&lt;/li&gt;
&lt;li&gt;Design reviews&lt;/li&gt;
&lt;li&gt;Frontend development&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;TailwindCSS&lt;/li&gt;
&lt;li&gt;Shadcn/ui&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Backend:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Express.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Database:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Prisma&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other Tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clerk (auth)&lt;/li&gt;
&lt;li&gt;Cloudinary (images)&lt;/li&gt;
&lt;li&gt;Resend (email)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://motion.dev/" rel="noopener noreferrer"&gt;Motion&lt;/a&gt; (animation)&lt;/li&gt;
&lt;li&gt;Axios (API)&lt;/li&gt;
&lt;li&gt;react-slick (slider)&lt;/li&gt;
&lt;li&gt;react-medium-image-zoom (image zoom)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4grmus9uqhyrjouccc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4grmus9uqhyrjouccc7.png" alt="Tech Stack" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  About the App: &lt;strong&gt;Oiwai&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Oiwai is a simple app to manage kids’ birthday parties.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosts can manage the budget and guest list
&lt;/li&gt;
&lt;li&gt;Guests can check all the party info in one place
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app name 'Oiwai' comes from the Japanese word meaning 'to celebrate'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxaadkp24ctef2my60vq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxaadkp24ctef2my60vq1.png" alt="Oiwai image" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Idea and Planning
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Brainstorming
&lt;/h4&gt;

&lt;p&gt;One team member has a 2-year-old child, so we decided to build a kids-related service. We wanted to make something useful for us too.&lt;/p&gt;
&lt;h4&gt;
  
  
  Defining the Problem
&lt;/h4&gt;

&lt;p&gt;We started by writing a simple problem statement:&lt;br&gt;
“What problem are we trying to solve?”&lt;/p&gt;

&lt;p&gt;This article was really helpful to us:&lt;a href="https://www.nngroup.com/articles/problem-statements/" rel="noopener noreferrer"&gt;Problem Statements in UX Discovery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjew2ajp1fpba2uzv094v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjew2ajp1fpba2uzv094v.png" alt="Project Objectives" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyiop2q3416znuc862yqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyiop2q3416znuc862yqc.png" alt="Problem Statemen" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We used the statement to decide on features for our MVP and create user stories.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97jhlyzpzrcwd3xgfamv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97jhlyzpzrcwd3xgfamv.png" alt="MVP features" width="800" height="888"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  User Stories
&lt;/h4&gt;

&lt;p&gt;We made two types of user stories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the host&lt;/li&gt;
&lt;li&gt;For the guest&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One person wrote the base, and we all reviewed it together.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3f5czvx2i2p57y1ezxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3f5czvx2i2p57y1ezxh.png" alt="For Host" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7fvnwvl47wca57935qf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7fvnwvl47wca57935qf.png" alt="For Guest" width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Wireframes &amp;amp; Design
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Wireframes (Low-fidelity)
&lt;/h4&gt;

&lt;p&gt;We listed all necessary screens and actions. I was in charge of the invitation flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y40mgbqdqzn2zlr3ybn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y40mgbqdqzn2zlr3ybn.png" alt="Wireframes" width="800" height="815"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Design (High-fidelity)
&lt;/h4&gt;

&lt;p&gt;After the wireframes, we made the UI design.&lt;br&gt;&lt;br&gt;
Another frontend member liked design too, so they took the lead. I helped with design reviews and taught how to use Figma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make an image board&lt;/li&gt;
&lt;li&gt;Choose a main color&lt;/li&gt;
&lt;li&gt;Collect reference designs&lt;/li&gt;
&lt;li&gt;Both of us designed 1 screen each to check direction&lt;/li&gt;
&lt;li&gt;Finalize and review each other’s work&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2os3ac2g6v9pmeeljhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2os3ac2g6v9pmeeljhj.png" alt="Design (High-fidelity)" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To save time, we used an 8px spacing system and design tokens for colors and fonts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahgzo4fxw7465me5mvr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahgzo4fxw7465me5mvr6.png" alt="Color tokens" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created 4 user flows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Landing page → Host&lt;/li&gt;
&lt;li&gt;Invitation for guest&lt;/li&gt;
&lt;li&gt;Guest event page&lt;/li&gt;
&lt;li&gt;After-party review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;a href="https://www.figma.com/proto/1l3niGh4ZAzR5rDv2SCi8X/Oiwai" rel="noopener noreferrer"&gt;Prototype Link&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. ER Diagram &amp;amp; Roadmap
&lt;/h3&gt;
&lt;h4&gt;
  
  
  ER Diagram
&lt;/h4&gt;

&lt;p&gt;The backend team made the ERD. We used &lt;a href="https://www.drawio.com/" rel="noopener noreferrer"&gt;draw.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vlrf32nnttnxmxmu3tj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vlrf32nnttnxmxmu3tj.png" alt="ERD" width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Roadmap
&lt;/h4&gt;

&lt;p&gt;Our PM made a roadmap based on screens. We estimated hours and managed tasks using GitHub Projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe393qvkke3rsw9ypjuiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe393qvkke3rsw9ypjuiw.png" alt="Roadmap" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Development
&lt;/h3&gt;
&lt;h4&gt;
  
  
  General Process
&lt;/h4&gt;

&lt;p&gt;While frontend worked on markup, backend created API docs. Once backend was ready, we connected the frontend.&lt;/p&gt;

&lt;p&gt;PRs were reviewed by the same-role member, and we had short daily stand-ups (30 min) to share updates.&lt;/p&gt;
&lt;h4&gt;
  
  
  Frontend Development
&lt;/h4&gt;

&lt;p&gt;Before jumping into development, we aligned on a few key things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Folder structure&lt;/li&gt;
&lt;li&gt;Component rules&lt;/li&gt;
&lt;li&gt;Naming conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We used Tailwind CSS along with shadcn/ui, and added &lt;code&gt;prettier-plugin-tailwindcss&lt;/code&gt; to keep our styles clean and consistent.&lt;/p&gt;

&lt;p&gt;This really helped us reduce miscommunication and keep our code easy to read.&lt;/p&gt;
&lt;h4&gt;
  
  
  My Work
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtube.com/shorts/h2jcQtNtgwE?feature=share" rel="noopener noreferrer"&gt;Landing Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtube.com/shorts/vYRRbGDsZpE?feature=share" rel="noopener noreferrer"&gt;My Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtube.com/shorts/dOF5xz0uCkY?feature=share" rel="noopener noreferrer"&gt;Host Checklist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtube.com/shorts/Mwy4hYjzpwQ?feature=share" rel="noopener noreferrer"&gt;Guest RSVP &amp;amp; Album&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtube.com/shorts/WgxaLtn8-ec?feature=share" rel="noopener noreferrer"&gt;Guest View&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtube.com/shorts/BaTcvZB33OE?feature=share" rel="noopener noreferrer"&gt;Review Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Reusable Modal Components
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28e7hybux91glnh7287o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28e7hybux91glnh7287o.png" alt="Modal" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had a hard time implementing reusable modals. &lt;br&gt;
The modal looked something like the one in the attachment, and at first, I tried  to handle all patterns within a single component.&lt;br&gt;
After discussing with a teammate, I got some helpful advice:&lt;br&gt;
There are mainly two types of modals - ones that just have buttons, and ones that include input elements - so it might be faster and cleaner to split them into two separate modal components.&lt;/p&gt;

&lt;p&gt;Even managing just those two types was still a bit confusing, so I think it was a good call in the end.&lt;/p&gt;

&lt;p&gt;For the ones with input fields, I wanted to change the function that gets executed depending on the props, but it ended up having too many conditional branches... so I’m still not sure if that was the best approach 😅&lt;/p&gt;

&lt;p&gt;Here's the final code👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

type ModalProps = {
  trigger: ReactNode;
  title: string;
  description?: string;
  button?: ReactNode;
  deleteAction: (id?: string) =&amp;gt; Promise&amp;lt;{ success: boolean; message: string }&amp;gt;;
  id?: string;
  deleteErrorMessage: string;
  onSuccess?: () =&amp;gt; void;
};

export default function Modal({
  trigger,
  title,
  description,
  button,
  deleteAction,
  id,
  deleteErrorMessage,
  onSuccess,
}: ModalProps) {
  const [isLoading, setIsLoading] = useState&amp;lt;boolean&amp;gt;(false);
  const [isOpen, setIsOpen] = useState&amp;lt;boolean&amp;gt;(false);

  const { toast } = useToast();

  const handleDelete = async (e: FormEvent) =&amp;gt; {
    e.preventDefault();
    setIsLoading(true);

    try {
      if (id) {
        const response = await deleteAction(id);
        if (response.success) {
          setIsOpen(false);
          if (onSuccess) {
            onSuccess();
          }
        }
        return;
      }

      if (!id &amp;amp;&amp;amp; deleteAction) {
        const response = await deleteAction();
        if (response.success) {
          setIsOpen(false);
          return;
        }
      }

      throw new Error("Invalid ID and no delete action available.");
    } catch (error) {
      if (error instanceof Error) {
        showErrorToast(toast, error.message, deleteErrorMessage);
      } else {
        showErrorToast(toast, "Failed to delete user", deleteErrorMessage);
      }
    } finally {
      setIsLoading(false);
    }
  };

  return (
    &amp;lt;Dialog open={isOpen} onOpenChange={setIsOpen}&amp;gt;
      &amp;lt;DialogTrigger asChild&amp;gt;{trigger}&amp;lt;/DialogTrigger&amp;gt;
      &amp;lt;DialogContent className="bg-white"&amp;gt;
        &amp;lt;DialogHeader&amp;gt;
          &amp;lt;DialogTitle&amp;gt;{title}&amp;lt;/DialogTitle&amp;gt;
          {description &amp;amp;&amp;amp; &amp;lt;DialogDescription&amp;gt;{description}&amp;lt;/DialogDescription&amp;gt;}
        &amp;lt;/DialogHeader&amp;gt;
        &amp;lt;DialogFooter className="flex flex-row justify-between gap-4"&amp;gt;
          &amp;lt;DialogClose asChild&amp;gt;
            &amp;lt;Button type="button" variant="outline" className="w-full bg-white"&amp;gt;
              Cancel
            &amp;lt;/Button&amp;gt;
          &amp;lt;/DialogClose&amp;gt;
          &amp;lt;Button
            type="submit"
            className="w-full bg-error font-bold shadow-none hover:bg-error/70 focus:bg-error active:bg-error"
            onClick={handleDelete}
          &amp;gt;
            {isLoading ? &amp;lt;Loader /&amp;gt; : button}
          &amp;lt;/Button&amp;gt;
        &amp;lt;/DialogFooter&amp;gt;
      &amp;lt;/DialogContent&amp;gt;
    &amp;lt;/Dialog&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

type PersonModalProps = {
  trigger?: ReactNode;
  title: string;
  defaultName?: string;
  defaultImage?: string;
  type: "user" | "family" | "guest";
  mode?: "new" | "edit";
  familyId?: string;
  eventId?: string;
  errorMessage: string;
  onSuccess?: () =&amp;gt; void;
};

export default function PersonModal({
  trigger,
  title,
  defaultName,
  defaultImage = "/images/profile_default.png",
  type,
  mode,
  familyId,
  eventId,
  errorMessage,
  onSuccess,
}: PersonModalProps) {
  const [isLoading, setIsLoading] = useState&amp;lt;boolean&amp;gt;(false);
  const [imageUrl, setImageUrl] = useState&amp;lt;string&amp;gt;(defaultImage);
  const [imageUrlData, setImageUrlData] = useState&amp;lt;File | null&amp;gt;(null);
  const [name, setName] = useState&amp;lt;string&amp;gt;(defaultName || "");
  const [isOpen, setIsOpen] = useState&amp;lt;boolean&amp;gt;(false);

  const inputImageRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null!);
  const { toast } = useToast();

  const defaultImagePath = "/images/profile_default.png";

  useEffect(() =&amp;gt; {
    if (isOpen) {
      setName(defaultName || "");
      setImageUrl(defaultImage);
    }
  }, [isOpen, defaultName, defaultImage]);

  // image functions
  const handleImageClick = (e: React.MouseEvent) =&amp;gt; {
    e.preventDefault();
    e.stopPropagation();
    inputImageRef.current.click();
  };

  const revokeObjectURL = useCallback(() =&amp;gt; {
    if (imageUrl.startsWith("blob:")) {
      URL.revokeObjectURL(imageUrl);
    }
  }, [imageUrl]);

  const handleImageDelete = (e: React.MouseEvent) =&amp;gt; {
    e.preventDefault();
    e.stopPropagation();
    revokeObjectURL();
    setImageUrl(defaultImagePath);
    setImageUrlData(null);
  };

  const handleImageChange = async (e: React.ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    const file = e.target.files?.[0];
    if (file) {
      const imageUrl = URL.createObjectURL(file);
      setImageUrlData(file);
      setImageUrl(imageUrl);
      revokeObjectURL();
    }
  };

  const handleNameChange = (e: React.ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    setName(e.target.value);
  };

  const resetForm = () =&amp;gt; {
    setName(defaultName || "");
    revokeObjectURL();
    setImageUrl(defaultImage);
  };

  const handleSubmit = async (e: FormEvent) =&amp;gt; {
    e.preventDefault();
    setIsLoading(true);

    try {
      let response;
      const updateData: { name: string; profileImageUrl?: File | null } = {
        name,
      };

      if (imageUrlData) {
        updateData.profileImageUrl = imageUrlData;
      } else if (imageUrlData === defaultImagePath) {
        updateData.profileImageUrl = null;
      }

      if (type === "user") {
        response = await updateUserInfo(updateData);
      } else if (familyId &amp;amp;&amp;amp; type === "family") {
        response = await updateFamilyInfo({
          familyId,
          ...updateData,
        });
      } else if (eventId &amp;amp;&amp;amp; type === "guest") {
        response = await addTemporaryParticipant(eventId, name);
      }

      if (mode === "new") {
        response = await addFamilyMember(updateData);
      }

      if (!response?.success) {
        notFound();
      }

      setIsOpen(false);
      resetForm();

      if (onSuccess) {
        onSuccess();
      }
    } catch (err: unknown) {
      if (err instanceof Error) {
        showErrorToast(toast, err.message, errorMessage);
      } else {
        showErrorToast(toast, "Unknown error occurred", errorMessage);
      }
    } finally {
      setIsLoading(false);
    }
  };

  useEffect(() =&amp;gt; {
    return () =&amp;gt; {
      revokeObjectURL();
    };
  }, [revokeObjectURL, imageUrl]);

  return (
    &amp;lt;Dialog open={isOpen} onOpenChange={setIsOpen}&amp;gt;
      &amp;lt;DialogTrigger asChild&amp;gt;
        {trigger ? (
          trigger
        ) : (
          &amp;lt;Button className="h-8 w-8 rounded-full bg-textSub/20 text-textSub shadow-none hover:bg-textSub/20 hover:opacity-70"&amp;gt;
            &amp;lt;PencilLineIcon /&amp;gt;
          &amp;lt;/Button&amp;gt;
        )}
      &amp;lt;/DialogTrigger&amp;gt;
      &amp;lt;DialogContent
        className="gap-6 bg-white"
        onClick={(e) =&amp;gt; e.stopPropagation()}
      &amp;gt;
        &amp;lt;DialogHeader&amp;gt;
          &amp;lt;DialogTitle className="text-left"&amp;gt;{title}&amp;lt;/DialogTitle&amp;gt;
        &amp;lt;/DialogHeader&amp;gt;
        &amp;lt;form onSubmit={handleSubmit} className="grid gap-6"&amp;gt;
          &amp;lt;div className="grid justify-items-center gap-4"&amp;gt;
            {type !== "guest" &amp;amp;&amp;amp; (
              &amp;lt;&amp;gt;
                &amp;lt;div className="relative"&amp;gt;
                  &amp;lt;button
                    type="button"
                    className="absolute -right-8"
                    onClick={handleImageDelete}
                  &amp;gt;
                    &amp;lt;X size={14} /&amp;gt;
                  &amp;lt;/button&amp;gt;
                  &amp;lt;button type="button" onClick={handleImageClick}&amp;gt;
                    &amp;lt;Image
                      src={imageUrl}
                      alt={name}
                      className="h-16 w-16 rounded-full object-cover"
                      width={64}
                      height={64}
                    /&amp;gt;
                  &amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;input
                  type="file"
                  id="image"
                  name="image"
                  onChange={handleImageChange}
                  hidden
                  ref={inputImageRef}
                /&amp;gt;
              &amp;lt;/&amp;gt;
            )}
            &amp;lt;div className="grid w-full gap-2"&amp;gt;
              &amp;lt;Label htmlFor="name"&amp;gt;Name&amp;lt;/Label&amp;gt;
              &amp;lt;Input
                id="name"
                name="name"
                required
                onChange={handleNameChange}
                value={name}
              /&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;

          &amp;lt;DialogFooter className="flex flex-row justify-between gap-4"&amp;gt;
            &amp;lt;DialogClose asChild&amp;gt;
              &amp;lt;Button
                type="button"
                variant="outline"
                className="w-full bg-white"
              &amp;gt;
                Cancel
              &amp;lt;/Button&amp;gt;
            &amp;lt;/DialogClose&amp;gt;
            &amp;lt;Button type="submit" className="w-full font-bold shadow-none"&amp;gt;
              {isLoading
                ? "Updating..."
                : mode === "new"
                  ? "Add"
                  : mode === "edit"
                    ? "Update"
                    : "Submit"}
            &amp;lt;/Button&amp;gt;
          &amp;lt;/DialogFooter&amp;gt;
        &amp;lt;/form&amp;gt;
      &amp;lt;/DialogContent&amp;gt;
    &amp;lt;/Dialog&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Checking the API Documentation
&lt;/h4&gt;

&lt;p&gt;Although I got used to it later on, in the beginning I only checked the response and didn’t properly read through the documentation.&lt;/p&gt;

&lt;p&gt;For example, I once missed the note saying that the request body should be of type &lt;code&gt;Content-Type: multipart/form-data&lt;/code&gt; (as shown in the attached image), and ended up wasting quite a bit of time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupqik4okecj5j0n0a2zc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupqik4okecj5j0n0a2zc.png" alt="API Documentation" width="800" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still, I’m glad I got to learn how handling image data is different from sending text or numbers, and also how to immediately display inputted image data on screen after uploading.&lt;/p&gt;

&lt;h4&gt;
  
  
  Naming Conventions
&lt;/h4&gt;

&lt;p&gt;In my previous job, I used class names like &lt;code&gt;Container&lt;/code&gt; or &lt;code&gt;Wrap&lt;/code&gt; for wrapper elements when writing markup. So, I kept using names like &lt;code&gt;〇〇Container&lt;/code&gt; for components as well.&lt;/p&gt;

&lt;p&gt;However, during a review, I was told that &lt;code&gt;Container&lt;/code&gt; is a bit too abstract and that my naming pattern was a bit limited. I also got feedback that similar names like &lt;code&gt;ParticipantListItem&lt;/code&gt; and &lt;code&gt;ParticipantItem&lt;/code&gt; can be confusing, and I should be more mindful of that.&lt;/p&gt;

&lt;p&gt;I realized I still lack the perspective of someone completely new to the codebase, and I’d like to improve this moving forward!&lt;/p&gt;

&lt;h4&gt;
  
  
  Scroll Position &amp;amp; shadcn Form Components
&lt;/h4&gt;

&lt;p&gt;I struggled through lots of small roadblocks but managed to push forward with trial and error.&lt;br&gt;&lt;br&gt;
One of the hardest parts was using &lt;code&gt;shadcn/ui&lt;/code&gt;'s form component. Writing validations with &lt;code&gt;zod&lt;/code&gt; was tricky, and dealing with type errors took more time than expected.&lt;/p&gt;

&lt;p&gt;I also wasn’t sure whether to use that form component or go with a Next.js server action for submitting forms.&lt;br&gt;&lt;br&gt;
It made me wonder how experienced engineers decide what to use when dealing with more complex forms.&lt;/p&gt;

&lt;p&gt;Another challenge was handling the scroll position.&lt;br&gt;&lt;br&gt;
When going back to a previous page via breadcrumb or link, the scroll position was preserved, which sometimes caused elements to be partially hidden.&lt;br&gt;&lt;br&gt;
I tried setting &lt;code&gt;scroll={true}&lt;/code&gt; as suggested in some articles, but it didn’t work well. In the end, I wrote a custom function to reset the scroll position on the relevant pages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

import { useEffect } from "react";

export default function ScrollToTop() {
  useEffect(() =&amp;gt; {
    window.scrollTo(0, 0);
  }, []);
  return null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That said, I’m not confident that this is the best approach—I'd love to learn what the recommended solution would be! 👀&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;I learned the whole process of building a project using &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Node.js&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Although I had some backend classes, I didn’t write much backend code this time—just skimmed through what others wrote. So, I want to practice building small backend apps myself!&lt;/p&gt;

&lt;p&gt;I also realized (as obvious as it may sound) how different the thought process is between designing and implementing a UI.&lt;br&gt;&lt;br&gt;
When designing, I focused on organizing UI elements while imagining user flows. But when coding, I had to think about what kind of data comes from the API and how it’s fetched, which required much more concrete thinking.&lt;/p&gt;

&lt;p&gt;This is something I lacked before, and also a big reason why I wanted to learn more frontend skills.&lt;/p&gt;

&lt;p&gt;By the way, the other frontend teammate who’s also into design had previous engineering experience, so they were already thinking about the API while designing. I thought that was really cool.&lt;/p&gt;

&lt;p&gt;When you have to design fast, it would be ideal to not only focus on usability, layout, and visual design—but also keep data flow in mind. That’s what I want to aim for.&lt;/p&gt;

&lt;p&gt;I’m always learning a lot from the designers I work with.&lt;br&gt;&lt;br&gt;
They propose ideal UI designs while also keeping implementation in mind, and I really admire that balance. I want to be able to do the same!&lt;/p&gt;

&lt;p&gt;This time, we only used color tokens, but I’m also interested in learning more about design/frontend crossover areas like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI management using &lt;strong&gt;Storybook&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; (which I’ve heard about a lot recently)&lt;/li&gt;
&lt;li&gt;Building components with &lt;strong&gt;Figma → Cursor&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🙌 Hoping to grow in those areas too!&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/kakimaru/oiwai" rel="noopener noreferrer"&gt;https://github.com/kakimaru/oiwai&lt;/a&gt;&lt;br&gt;
Figma: &lt;a href="https://www.figma.com/design/1l3niGh4ZAzR5rDv2SCi8X/Oiwai?node-id=70-5925&amp;amp;t=MN61YXeTtCPcNe7W-1" rel="noopener noreferrer"&gt;https://www.figma.com/design/1l3niGh4ZAzR5rDv2SCi8X/Oiwai?node-id=70-5925&amp;amp;t=MN61YXeTtCPcNe7W-1&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/haruka-kakiuchi-profile/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/haruka-kakiuchi-profile/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Through this project, I feel like I’ve significantly expanded my toolkit as a designer.&lt;br&gt;&lt;br&gt;
My goal is to grow into a &lt;strong&gt;design engineer&lt;/strong&gt; who contributes to the whole product—not just visuals—and I’ll keep challenging myself with more team-based development!&lt;/p&gt;

&lt;p&gt;If you’re planning to build a project from scratch, like for a hackathon, I hope this post gave you some helpful insights. Let’s do our best!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>frontend</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>How to fetch API - React</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Sun, 30 Jun 2024 20:41:18 +0000</pubDate>
      <link>https://forem.com/kakimaru/how-to-fetch-api-react-41e5</link>
      <guid>https://forem.com/kakimaru/how-to-fetch-api-react-41e5</guid>
      <description>&lt;p&gt;Using Pokemon api&lt;br&gt;
&lt;a href="https://pokeapi.co/" rel="noopener noreferrer"&gt;https://pokeapi.co/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How to get all data
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
import { getAllPokemon } from './utils/pokemon'

function App() {
  const initialURL = `https://pokeapi.co/api/v2/pokemon/`;

  useEffect(() =&amp;gt; {
    const fetchPokemonData = async function() {
      let res = await getAllPokemon(initialURL)
      console.log(res);
    }

    fetchPokemonData();
  }, [])


  return (
    &amp;lt;div className="App"&amp;gt;

    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const getAllPokemon = function (url) {
  return new Promise((resolve, reject) =&amp;gt; {
    fetch(url)
      .then((res) =&amp;gt; res.json())
      .then((data) =&amp;gt; resolve(data));
  });
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Read each of data
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [pokemonData, setPokemonData] = useState([])

  useEffect(() =&amp;gt; {
    const fetchPokemonData = async function() {
      let res = await getAllPokemon(initialURL)

      loadPokemon(res.results) // added
      setLoading(false)
    }


    fetchPokemonData();
  }, [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const loadPokemon = async function(data) {
    let _pokemonData = await Promise.all(data.map((item) =&amp;gt; {
      let pokemonRecord = getPokemon(item.url)
      return pokemonRecord;
    }))
    setPokemonData(_pokemonData)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Slider</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Tue, 11 Jun 2024 16:27:14 +0000</pubDate>
      <link>https://forem.com/kakimaru/slider-35fi</link>
      <guid>https://forem.com/kakimaru/slider-35fi</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Slider
const slider = function () {
  const slides = document.querySelectorAll('.slide');
  const btnLeft = document.querySelector('.slider__btn--left');
  const btnRight = document.querySelector('.slider__btn--right');
  const dotContainer = document.querySelector('.dots');

  let curSlide = 0;
  const maxSlide = slides.length;

  // Functions
  const createDots = function () {
    slides.forEach(function (_, i) {
      dotContainer.insertAdjacentHTML(
        'beforeend',
        `&amp;lt;button class="dots__dot" data-slide="${i}"&amp;gt;&amp;lt;/button&amp;gt;`
      );
    });
  };

  const activateDot = function (slide) {
    document
      .querySelectorAll('.dots__dot')
      .forEach(dot =&amp;gt; dot.classList.remove('dots__dot--active'));

    document
      .querySelector(`.dots__dot[data-slide="${slide}"]`)
      .classList.add('dots__dot--active');
  };

  const goToSlide = function (slide) {
    slides.forEach(
      (s, i) =&amp;gt; (s.style.transform = `translateX(${100 * (i - slide)}%)`)
    );
  };

  // Next slide
  const nextSlide = function () {
    if (curSlide === maxSlide - 1) {
      curSlide = 0;
    } else {
      curSlide++;
    }

    goToSlide(curSlide);
    activateDot(curSlide);
  };

  const prevSlide = function () {
    if (curSlide === 0) {
      curSlide = maxSlide - 1;
    } else {
      curSlide--;
    }
    goToSlide(curSlide);
    activateDot(curSlide);
  };

  const init = function () {
    goToSlide(0);
    createDots();
    activateDot(0);
  };
  init();

  // Event handlers
  btnRight.addEventListener('click', nextSlide);
  btnLeft.addEventListener('click', prevSlide);

  document.addEventListener('keydown', function (e) {
    if (e.key === 'ArrowLeft') prevSlide();
    e.key === 'ArrowRight' &amp;amp;&amp;amp; nextSlide();
  });

  dotContainer.addEventListener('click', function (e) {
    if (e.target.classList.contains('dots__dot')) {
      const { slide } = e.target.dataset;
      goToSlide(slide);
      activateDot(slide);
    }
  });
};
slider();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>IntersectionObserver</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Sun, 09 Jun 2024 07:35:45 +0000</pubDate>
      <link>https://forem.com/kakimaru/intersectionobserver-161c</link>
      <guid>https://forem.com/kakimaru/intersectionobserver-161c</guid>
      <description>&lt;p&gt;This memo from 'The Complete JavaScript Course 2024: From Zero to Expert!' on Udemy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const header = document.querySelector('.header');
const navHeight = nav.getBoundingClientRect().height;


const stickyNav = function (entries) {
  const [entry] = entries; // entries[0]

  if (!entry.isIntersecting) nav.classList.add('sticky');
  else nav.classList.remove('sticky');
};

const headerObserver = new IntersectionObserver(stickyNav, {
  root: null,
  threshold: 0,
  rootMargin: `-${navHeight}px`,
});
headerObserver.observe(header);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bad way(The performance of the app on mobile devices is affected by the firing of an event on every scroll.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initialCoords = section1.getBoundingClientRect()

window.addEventListener('scroll', function(e) {
  console.log(window.scrollY);
  if(window.scrollY &amp;gt; initialCoords.top) nav.classList.add('sticky');
  else nav.classList.remove('sticky')

})

const obsCallback = function (entries, observer) {
  entries.forEach(entry =&amp;gt; {
    console.log(entry);
  });
};

const obsOptions = {
  root: null,
  threshold: [0, 0.2], // [0, 1, 0.2] (100%)
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll revealing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const allSections = document.querySelectorAll('.section')

const revealSection = function(entries, observer) {
  const [entry] = entries;

  if(!entry.isIntersecting) return; // Guard

  entry.target.classList.remove('section--hidden')
  observer.unobserve(entry.target) // for paformance
}

const sectionObserver = new IntersectionObserver(revealSection, {
  root: null,
  threshold: 0.15,
})

allSections.forEach(function(section) {
  sectionObserver.observe(section)
  section.classList.add('section--hidden') // for everyone can see the section including person who block JS
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Tabs</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Sun, 09 Jun 2024 06:30:53 +0000</pubDate>
      <link>https://forem.com/kakimaru/tabs-2e6l</link>
      <guid>https://forem.com/kakimaru/tabs-2e6l</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="tabs_wrap"&amp;gt;
  &amp;lt;div class="tabs_container"&amp;gt;
    &amp;lt;button class="btn tab tab--1 tab--active" data-tab="1"&amp;gt;
      tab button 1
    &amp;lt;/button&amp;gt;
    &amp;lt;button class="btn tab tab--2 tab--active"  data-tab="2"&amp;gt;
      tab button 2
    &amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class="content content--1 content--active"&amp;gt;
    &amp;lt;div&amp;gt;
      contents 1
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class="content content--2 content--active"&amp;gt;
    &amp;lt;div&amp;gt;
      contents 2
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const tabs = document.querySelectorAll('.tab');
const tabsContainer = document.querySelector('.tabs_container');
const tabsContent = document.querySelectorAll('.content');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tabsContainer.addEventListener('click', function (e) {
  const clicked = e.target.closest('.tab');

  // Guard clause
  if (!clicked) return;

  // Remove active classes
  tabs.forEach(t =&amp;gt; t.classList.remove('tab--active'));
  tabsContent.forEach(c =&amp;gt; c.classList.remove('content--active'));

  // Activate tab
  clicked.classList.add('tab--active');

  // Activate content area

 document.querySelector(`.content-${clicked.dataset.tab}`).classList.add('content--active');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid using &lt;code&gt;forEach&lt;/code&gt; to attach events to each tab. Instead, leverage event bubbling to set an event listener on the parent element and determine which child element it corresponds to.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Smooth Scroll</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Sun, 09 Jun 2024 02:27:18 +0000</pubDate>
      <link>https://forem.com/kakimaru/smooth-scroll-oil</link>
      <guid>https://forem.com/kakimaru/smooth-scroll-oil</guid>
      <description>&lt;p&gt;Conventional way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const hoge = hoge.getBoundingClientRect();

window.scrollTo({
  left : hoge.left + window.pageXOffset, 
  top: hoge.top + window.pageYOffset,
  behavior: 'smooth',
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recently way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hoge.scrollIntoView({behavior: "smooth"})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Viewport version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.documentElement.clientHeight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Display the current time</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Fri, 07 Jun 2024 02:08:40 +0000</pubDate>
      <link>https://forem.com/kakimaru/display-the-current-time-4607</link>
      <guid>https://forem.com/kakimaru/display-the-current-time-4607</guid>
      <description>&lt;p&gt;Goal: 01 / 01 / 2000, 12:00&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const now = new Date();
const day = `${now.getDate()}`.padStart(2, '0');
const month = `${now.getMonth() + 1}`.padStart(2, '0');
const year = now.getFullYear();
const hour = now.getHours();
const min = now.getMinutes();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;padStart() needs to be used with a string.&lt;/li&gt;
&lt;li&gt;padStart() fills the first argument's number of minutes with the elements of the second argument.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hoge.textContent = `${day}/${month}/${year}, ${hour}:${min}`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If I want to show 'TODAY' or 'Yesterday' when the day is matched.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const calcDayPassed = (date1, date2) =&amp;gt; Math.round(Math.abs(date2 - date1) / (1000 * 60 * 60 * 24)); // get time stamp

  const daysPassed = calcDayPassed(new Date(), date) 

  if(daysPassed === 0) return 'Today';
  if(daysPassed === 1) return 'Yesterday';
  if(daysPassed &amp;lt;= 7) return `${daysPassed} days ago`;
  else {
    const day = `${date.getDate()}`.padStart(2, '0');
    const month = `${date.getMonth() + 1}`.padStart(2, '0');
    const year = date.getFullYear();
    return `${day}/${month}/${year}`;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Globalisation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const now = new Date();
const options = {
 hour: 'numeric',
 minute: 'numeric',
 day: 'numeric',
 month: 'numeric',
 year: `numeric`,
}

const locale = navigator.language;

hoge.textContent = new Intl.DateTimeFormat(currentAccount.locale, options).format(now);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat" rel="noopener noreferrer"&gt;MDN : Int&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Simple Modal with Javascript</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Tue, 04 Jun 2024 23:01:01 +0000</pubDate>
      <link>https://forem.com/kakimaru/simple-modal-with-javascript-35nl</link>
      <guid>https://forem.com/kakimaru/simple-modal-with-javascript-35nl</guid>
      <description>&lt;p&gt;This is a note that how to make a simple modal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"show-modal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show modal &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"close-modal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;times;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;I'm a modal window&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
        veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
        commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
        velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
        occaecat cupidatat non proident, sunt in culpa qui officia deserunt
        mollit anim id est laborum.
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.hidden&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3rem&lt;/span&gt; &lt;span class="m"&gt;5rem&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="m"&gt;.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="m"&gt;.6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.modal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.overlay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;btnCloseModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.close-modal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;btnOpenModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.show-modal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closeModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;modal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;modal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// if there are many open buttons&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;btnOpenModal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;btnOpenModal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;openModal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;btnCloseModal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;closeModal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;closeModal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// keyboard operation (Escape version)&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;modal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;closeModal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for -&amp;gt; forEach&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// if there are many open buttons
for (let i = 0; i &amp;lt; btnOpenModal.length; i++) {
  btnOpenModal[i].addEventListener("click", openModal);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;↓&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;btnOpenModal.forEach(btn =&amp;gt; btn.addEventListner('click', openModal)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>My Engineering Journey Begins!</title>
      <dc:creator>Haruka Kakiuchi</dc:creator>
      <pubDate>Fri, 03 May 2024 03:22:06 +0000</pubDate>
      <link>https://forem.com/kakimaru/my-engineering-journey-begins-24ak</link>
      <guid>https://forem.com/kakimaru/my-engineering-journey-begins-24ak</guid>
      <description>&lt;p&gt;Hi, I'm Haruka. &lt;br&gt;
I am studying Web development at CICCC in Vancouver.&lt;/p&gt;

&lt;p&gt;This article is my first assignment.&lt;br&gt;
I'll introduce my self and write about expectation for the course.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nationality: Japanese&lt;/li&gt;
&lt;li&gt;Education: Bachelor's Degree in Economics&lt;/li&gt;
&lt;li&gt;Skills: Self-taught UI Designer&lt;/li&gt;
&lt;li&gt;Experience: UI Designer at &lt;a href="https://palan.co.jp/en" rel="noopener noreferrer"&gt;palan,inc&lt;/a&gt;, an Augmented Reality company&lt;/li&gt;
&lt;li&gt;Interests: Food, Sleep, Gaming&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My expectations for the course
&lt;/h2&gt;

&lt;p&gt;For three years, I thrived as a UI designer, gaining valuable experience. However, I yearned to delve deeper into the fundamental workings of the products I designed.&lt;/p&gt;

&lt;p&gt;The services I worked on utilized Ruby on Rails and JavaScript(including Three.js etc). While my role focused on UI design, my lack of knowledge in these languages limited the scope of my contributions.&lt;/p&gt;

&lt;p&gt;Particularly captivated by Figma, I attempted to create plugins. However, insufficient knowledge and limited time for dedicated learning proved to be roadblocks.&lt;/p&gt;

&lt;p&gt;Driven by this desire to expand my skillset, I choose this course. My primary goals are to gain proficiency in JavaScript and independently create projects by the course's completion.&lt;/p&gt;

&lt;p&gt;This program offers a unique structure with one year dedicated to learning and a subsequent year focused on practical application. During the practical year, I aspire to join a new team as either a front-end engineer or UI designer.&lt;/p&gt;

&lt;p&gt;By mastering front-end language, I aim to establish a robust design system foundation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How was my experience with the first week
&lt;/h2&gt;

&lt;p&gt;In the first week, I've been diving into the foundational concepts of computers, and there's been a surprising amount of new information to absorb. I'm really enjoying the process.&lt;/p&gt;

&lt;p&gt;One topic that particularly piqued my interest was networking. It's fascinating to learn how servers located around the world connect with my IP address to ensure the fastest response time. It's a complex system, but understanding its core function has been incredibly insightful.&lt;/p&gt;

&lt;p&gt;The number systems class was also interesting. While I knew computers utilize a binary system with 0 and 1, the deeper dive into this concept provided a much clearer understanding. &lt;/p&gt;

&lt;p&gt;Another unexpected discovery this week was about ASCII.&lt;br&gt;
In Japan, ASCII art used by early internet users for online bulletin boards. I had no idea the origins of the format, so learning about it was a pleasant surprise.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I want to achieve after the course?
&lt;/h2&gt;

&lt;p&gt;As I wrote in this article, I aspire to join new team as either a front-engineer or a UI designer.&lt;/p&gt;

&lt;p&gt;I hope my dedication to learning to learn the language will have a positive impact on my life.&lt;/p&gt;

&lt;p&gt;Shared with: Risa, Evangelina&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
