TODO-APP using SVELTE
Tags: webdev, svelte, tutorial, beginners
Published: 2023-03-20 06:14:25


![project preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxe89a037aj47twcbhql.png)

## Step 1: Set Up Your Environment
Before you start coding, you need to set up your development environment. First, make sure you have Node.js installed on your machine. You can download Node.js from the official website: https://nodejs.org/en/download/.

Once Node.js is installed, you can use the Node Package Manager (npm) to install the Svelte CLI. Open a command prompt or terminal and run the following command:

``npm install -g svelte-cli`` 
This command installs the Svelte CLI globally on your machine, which allows you to create new Svelte projects and run development servers.

---

## Step 2: Create a New Svelte Project
Once the Svelte CLI is installed, you can use it to create a new Svelte project. Navigate to the directory where you want to create your project and run the following command:

``svelte create my-todo-list``
Replace "my-todo-list" with the name of your project. This command creates a new Svelte project with the default template.

---


## Step 3: Create the Layout Component
In Svelte, components are the building blocks of your application. You can think of a component as a reusable piece of code that encapsulates its own logic and user interface.

The first component we need to create is the layout component. This component will define the overall structure of our application, such as the header, footer, and navigation.

Create a new file called _Layout.svelte_ in the _src/components_ directory and add the following code:

```
<script>
	import './styles.css';
</script>

<div class="app">
	<main>
		<slot />
	</main>
</div>
```
## Step 4: Update the style.css and include assets 
update the style.css with this code 

```
body {
	margin: 0;
	padding:0;
	background: url(../lib/images/pexels-andrew-neel-2312369.jpg);
	background-repeat: no-repeat;
	background-size: cover;
	background-position: center;
	min-height: 100vh;
}

*{
	margin: 0;
	padding:0;
	box-sizing: border-box;
}

.app{
	background: rgba(21, 21, 21, 0.47);
	z-index: 999;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
```
include assests in a image folder inside the lib folder.

## Step 5: Create a _+page.svelte_ inside routes

inside the the file include this code 

```
<script>
	import Icon from '$lib/images/add.png';
	let todos = [];
	let tag = 'work';
	const tagsToEmoji = {
		work: '💼',
		study: '📚',
		read:'📖',
		write:'✍🏼',
		draw: '🎨',
		exercise:'🏃',
		hobby: '🎮',
		swimming: '🏊'
	};
	let task = '';
	let filter = 'all';
	function addTask() {
		todos = [
			{
				task: task,
				status: 'pending',
				tag: tag
			},
			...todos
		];
		task = '';
	}
	function markComplete(i) {
		todos[i].status = 'completed';
		todos = [...todos];
	}
	function removeTask(i) {
		todos.splice(i, 1);
		todos = [...todos];
	}
</script>

<svelte:head>
	<title>Home</title>
	<meta name="description" content="Svelte demo app" />
</svelte:head>

<div class="container">
	<div class="todo">
		<div class="form">
			<input
				type="text"
				bind:value={task}
				on:keydown={(e) => {
					if (e.key === 'Enter') {
						addTask();
					}
				}}
			/>

			<button on:click={addTask}>
				<img src={Icon} alt="" srcset="" />
			</button>
			<select bind:value={tag}>
				<option value="work">Work</option>
				<option value="study">Study</option>
				<option value="draw">Drawing</option>
				<option value="read">Reading</option>
				<option value="hobby">Hobby</option>
				<option value="swimming">Swimming</option>
				<option value="exercise">Exercise</option>
				<option value="write">Writing</option>
			</select>
		</div>
		<div class="filters">
			<button
				class={filter == 'all' ? 'active' : ''}
				on:click={() => {
					filter = 'all';
				}}
			>
				All
			</button>
			<button
				class={filter == 'completed' ? 'active' : ''}
				on:click={() => {
					filter = 'completed';
				}}
			>
				Completed
			</button>
			<button
				class={filter == 'incomplete' ? 'active' : ''}
				on:click={() => {
					filter = 'incomplete';
				}}
			>
				Incomplete
			</button>
		</div>
		<div class={todos.length > 0 ? 'tasks' : ''}>
			{#each todos as todo, i}
				{#if filter == 'all'}
					<div class="task">
						<div class={todo.status == 'completed' ? 'active-ul' : ''}>
							{todo.task}
						</div>
						<span>{tagsToEmoji[todo.tag]}</span>						
						<button
							class={todo.status == 'completed' ? 'active' : ''}
							on:click={() => {
								markComplete(i);
							}}
						>
							&#10004;
						</button>
						<button
							on:click={() => {
								removeTask(i);
							}}
						>
							&#10006;
						</button>
					</div>
				{:else if filter == 'completed'}
					{#if todo.status == 'completed'}
						<div class="task">
							<div>
								{todo.task}
							</div>
							<button
								on:click={() => {
									removeTask(i);
								}}
							>
								&#10006;
							</button>
						</div>
					{/if}
				{:else if todo.status == 'pending'}
					<div class="task">
						<div>
							{todo.task}
						</div>
						<button
							class={todo.status == 'completed' ? 'active' : ''}
							on:click={() => {
								markComplete(i);
							}}
						>
							&#10004;
						</button>
					</div>
				{/if}
			{/each}
		</div>
	</div>
</div>

<style>
	.todo {
		padding: 20px;
		opacity: 0.8;
		width: 70vw;
		height: auto;
		border-radius: 20px;
		background: white;
	}

	.todo > div {
		margin: 20px 0px;
	}

	.todo .form {
		display: flex;
		align-items: center;
		justify-content: space-around;
		height: fit-content;
		border: 1px solid grey ;
		border-radius: 15px;
		padding: 5px;
	}

	img {
		height: 20px;
		object-fit: cover;
	}

	input,
	button {
		background: transparent;
		border: none;
	}

	input {
		border-top-left-radius: 8px;
		border-right: none;
		height: 35px;
		width: calc(70vw);
		padding: 2px;
		font-size: 22px;
	}

	input:focus {
		outline: none;
	}
	.form button {
		border-left: none;
		height: 35px;
		border-top-right-radius: 8px;
		padding: 2px;
		cursor: pointer;
	}

	.tasks {
		border: 1px solid grey;
		border-top-right-radius: 20px;

		border-top-left-radius: 20px;
		padding: 20px 5px;
	}

	.task {
		border-top: 1px solid grey;
		word-wrap: break-word;
		font-size: 20px;
		display: flex;
		align-items: center;
		padding: 10px;
	}
	.task span {
		margin-left: 5px;
		margin-right: 8px;
	}

	.todo .tasks > .task > button {
		width: 25px;
		height: 25px;
		border: 1px solid #000000;
		color: #000000;
		border-radius: 50%;
		margin: 0px 5px;
		cursor: pointer;

	}
	.todo .tasks > .task > button.active {
		background: #020202;
		color: #f5f5f5;
	}
	.todo .filters {
		display: flex;
		justify-content: space-between;
	}
	.todo .filters > button {
		min-width: 150px;
		padding: 10px 8px;
		border-bottom: 1px solid #000000ce;
		cursor: pointer;
		font-size: 20px;
	}
	.todo .filters > button.active {
		background: #000000;
		color: #f5f5f5;
	}
	select{
		padding: 10px;
		margin: 3px;
		font-size: 20px;
	}
	.active-ul{
		text-decoration: line-through;
	}
</style>

```
You can update the style as you wish , If you feel discomfort with the way of structure of the code , Try to read the sevlte documentation to know about how to include style script and html combined in a single file .

explanation for the script section :-

Let's break down the different parts:

- import Icon from '$lib/images/add.png';: This line imports an image from the src/lib/images directory. This image will be used as an icon for the "Add" button in the component's UI.

- let todos = [];: This creates an empty array called todos. This array will store the to-do items that the user adds.

- let tag = 'work';: This sets the initial value of the tag variable to 'work'. This variable is used to store the selected tag for a new to-do item.

- const tagsToEmoji = {...};: This creates an object called tagsToEmoji that maps each tag name to an emoji that represents that tag.

- let task = '';: This initializes the task variable to an empty string. This variable will store the text of a new to-do item that the user enters.

- let filter = 'all';: This initializes the filter variable to 'all'. This variable is used to filter the displayed to-do items based on their status (completed or pending).

- function addTask() {...}: This function is called when the user clicks the "Add" button to create a new to-do item. It creates a new object with the text of the task, the selected tag, and a status of "pending", and adds it to the beginning of the todos array. It then clears the task variable so the user can enter a new task.

- function markComplete(i) {...}: This function is called when the user clicks the "Complete" button on a to-do item. It changes the status property of the specified to-do item to "completed", and updates the todos array with the new status.

- function removeTask(i) {...}: This function is called when the user clicks the "Remove" button on a to-do item. It removes the specified to-do item from the todos array, and updates the array to reflect the change.

## Step 6: Save and run development server 
`npm run dev`

get the code on[ https://github.com/JoelJaison394/Todo_App-sevlte.git](https://github.com/JoelJaison394/Todo_App-sevlte.git)