ChatiumFor developersPlaygroundPricing
Sign in

Creating the First File


Before us is the development environment IDE, where all the files of our account are located. The list of files and folders is on the left side; there we can also add a new file. To do this, we use the bottom-left button called "Add File."

The first thing we will do is create a directory for our plugin. We need a directory because in the following steps we will turn it into a plugin for connecting to external accounts.

  • Click "Add File."
  • A file type selection will appear; choose Directory.

Enter the name plugin (you can choose any name you like, but further instructions will use this name).

Entering the directory name

The directory should now appear on the left side. After that, navigate into it and add the first file to this directory.

  • Click "Add File."
  • A file type selection will appear; choose Server TypeScript.

Creating server-side TypeScript

In the window that appears, enter the file name index and click the Create button:

Also, add the files script.js and style.css, as they will be useful later.

So, the files have been created.

We will be creating our web service in HTML style for now, so let's delete all the content of the file and insert our code.

ide_inter

index.tsx

import { jsx } from "@app/html-jsx";
import { Heap } from "@app/heap";

const Notes = Heap.Table("note", {
  title: Heap.String(),
  completed: Heap.Boolean(),
});

app.html("/", async (ctx) => {
  let notes = await Notes.findAll(ctx, { order: { title: "asc" } });
  return (
    <html>
      <head>
        <script src="./script.js"></script>
        <link rel="stylesheet" href="./style.css" />
      </head>
      <body>
        <h1>Task List</h1>
        <form id="addTaskForm" title="Create Task">
          <div>
            <input
              id="taskTitle"
              name="title"
              placeholder="Describe the task"
              required
            />
          </div>
          <div class="margin">
            <button onclick={`createTask('${createRoute.url()}')`}>
              Create Task
            </button>
          </div>
        </form>
        <div id="addTaskList">
          {notes.map((note) => {
            return (
              <div
                id="list"
                class="list"
              >
                <div class='task-container'>
                  <input
                    class="task-checkbox"
                    type="checkbox"
                    checked={note.completed}
                    onchange={`checkTask('${toggleRoute({
                      id: note.id,
                    }).url()}')`}
                  />
                  <span class="task-text">{note.title}</span>
                </div>

                <button
                  onclick={`deleteTask('${deleteRoute({ id: note.id }).url()}')`}
                  type="button" 
                  class="delete"
                >
                  Delete
                </button>
              </div>
            );
          })}
        </div>
      </body>
    </html>
  );
});

const createRoute = app.post("/create", async (ctx, req) => {
  ctx.account.log("click", { json: req });
  await Notes.create(ctx, {
    title: req.body.title,
    completed: false,
  });
  return;
});

const toggleRoute = app.post("/toggle/:id", async (ctx, req) => {
  ctx.account.log("done");
  let note = await Notes.getById(ctx, req.params.id);
  await Notes.update(ctx, { id: note.id, completed: !note.completed });
  return;
});

const deleteRoute = app.post("/delete/:id/submit", async (ctx, req) => {
  await Notes.delete(ctx, req.params.id);
  return;
});

script.js

const createTask = async(url)=> {
  // event.preventDefault(); // prevent page reload
  const title = document.getElementById('taskTitle').value
  const response = await fetch(url, {
   method: 'POST',
   body: new URLSearchParams({
       title: title,
    }),
   headers: {
     'Content-Type': 'application/x-www-form-urlencoded',
    },
   });
  location.reload();
};

const checkTask = async( url)=> {
 
  const response = await fetch(url, {
     method: 'POST',
     body: {},
    });
  location.reload();
};
const deleteTask = async( url)=> {
  
  const response = await fetch(url, {
     method: 'POST',
     body: {},
    });
  location.reload();
};

style.css

.task-container {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
  }

  /* Style for custom checkbox */
  .task-checkbox {
    appearance: none;
    width: 20px;
    height: 20px;
    border: 2px solid #000;
    border-radius: 4px;
    margin-right: 10px;
    position: relative;
    cursor: pointer;
  }

  /* Style for checkbox state with checkmark */
  .task-checkbox:checked {
    background-color: #4CAF50;
    border-color: #4CAF50;
  }

  .task-checkbox:checked::after {
    content: '✔';
    position: absolute;
    top: 0;
    left: 2px;
    color: white;
    font-size: 16px;
  }

  /* Style for task text */
  .task-text {
    font-size: 16px;
  }

  .list{
    margin-top: 2vh;
    width: 50vw; 
    display: flex; 
    justify-content: space-between;
    align-items: center;
  }

  .margin{
    margin: 15px 0px;
  }


  button {
    background-color: #4CAF50; 
    color: white; 
    border: none; 
    padding: 10px 20px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    cursor: pointer;
    border-radius: 5px; 
    transition: background-color 0.3s ease;
  }

  button[type="submit"]:hover {
    background-color: #45a049; 
  }

/* Styles for "Delete" buttons */
  button.delete {
    background-color: #f44336;
    color: white; 
    border: none; 
    padding: 5px 15px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 14px;
    cursor: pointer;
    border-radius: 5px; 
    transition: background-color 0.3s ease;
  }

  button.delete:hover {
    background-color: #da190b; 
  }

  /* Styles for input fields */
  input {
    width: 300px; 
    padding: 10px;
    margin: 10px 0; 
    border: 1px solid #ccc; 
    border-radius: 5px; 
    font-size: 16px; 
    outline: none; 
    transition: border-color 0.3s ease; 
  }

  /* Styles for input field on focus */
  input:focus {
    border-color: #4CAF50; 
  }

  /* Styles for placeholder */
  input::placeholder {
    color: #888; 
    font-style: italic;
  }

Save the file using the Save button, and you will see that the preview on the right has updated; it should look like this:

code

Next Step: Let's understand what this code does