Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/tech-andgar/ionic-angular-todo-app

๐Ÿ“‹ App created using the Ionic framework, using a firebase cloud database to store to-do data. All CRUD operations can be carried out using the Ionic UI.
https://github.com/tech-andgar/ionic-angular-todo-app

angular ionic ionic-framework todo

Last synced: 25 days ago
JSON representation

๐Ÿ“‹ App created using the Ionic framework, using a firebase cloud database to store to-do data. All CRUD operations can be carried out using the Ionic UI.

Awesome Lists containing this project

README

        

# # :zap: Ionic Todo App

## Overview

This project is a Todo App developed with Ionic, TypeScript, and Angular. It features a robust interface for managing todo items, including creating, reading, updating, and deleting them, as well as performing batch operations and managing resources. The app uses a Firebase cloud database for data storage and the [Ionic framework](https://ionicframework.com/docs) for its UI. The API is designed to be flexible and consistent, supporting various implementations while maintaining a unified interface.

- All CRUD operations can be performed through the Ionic UI.
- **Note:** To open web links in a new window, use _ctrl+click_ on the link.

![GitHub repo size](https://img.shields.io/github/repo-size/tech-andgar/ionic-angular-todo-app?style=plastic)
![GitHub pull requests](https://img.shields.io/github/issues-pr/tech-andgar/ionic-angular-todo-app?style=plastic)
![GitHub Repo stars](https://img.shields.io/github/stars/tech-andgar/ionic-angular-todo-app?style=plastic)
![GitHub last commit](https://img.shields.io/github/last-commit/tech-andgar/ionic-angular-todo-app?style=plastic)

## :page_facing_up: Table of contents

- [# :zap: Ionic Todo App](#-zap-ionic-todo-app)
- [Overview](#overview)
- [:page\_facing\_up: Table of contents](#page_facing_up-table-of-contents)
- [:cool: Features](#cool-features)
- [๐Ÿ“ฆ Installation Offline](#-installation-offline)
- [:camera: Screenshots](#camera-screenshots)
- [:signal\_strength: Technologies](#signal_strength-technologies)
- [๐ŸŒณ Project Structure](#-project-structure)
- [:floppy\_disk: Setup / Installation](#floppy_disk-setup--installation)
- [Usage](#usage)
- [Key Components](#key-components)
- [๐Ÿ“š API Reference](#-api-reference)
- [TodosApi](#todosapi)
- [Todo Retrieval Methods](#todo-retrieval-methods)
- [Todo Modification Methods](#todo-modification-methods)
- [Todo Deletion Methods](#todo-deletion-methods)
- [Batch Operations Methods](#batch-operations-methods)
- [Resource Management Methods](#resource-management-methods)
- [:computer: Code Examples - Implementation Details](#computer-code-examples---implementation-details)
- [LocalStorageTodosApi](#localstoragetodosapi)
- [๐Ÿงช Testing](#-testing)
- [โš ๏ธ Performance Considerations](#๏ธ-performance-considerations)
- [:clipboard: Status \& To-do list](#clipboard-status--to-do-list)
- [Contributing](#contributing)
- [:file\_folder: License](#file_folder-license)
- [:envelope: Contact](#envelope-contact)

## :cool: Features

**CRUD operations:**

- Create: Click '+' to create a to-do item.
- Read: Line items are displayed on the home page.
- Update: Click on item line to edit.
- Delete: swipe left and a colored 'DONE' button appears on the right.
- Batch operations (clear completed, complete all)
- Observable-based API for reactive programming
- Local storage persistence
- TypeScript for type safety
- Abstract API design for flexibility in implementation

## ๐Ÿ“ฆ Installation Offline

- [ANDROID APK (UNSIGNED)](./docs/installer/android/)

- [IOS IPA (UNSIGNED)](./docs/installer/ios/)

## :camera: Screenshots

![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-multilanguage.png)
![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-web.png)
![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-category.png)
![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-filter-category.png)
![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-slide.png)
![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-options.png)
![todo items shown on ionic frontend and Firestore database](./docs/imgs/todo-app-undo.png)
![todo](./docs/video/todo-app.mp4)

## :signal_strength: Technologies

- [Ionic/angular v8](https://ionicframework.com/)
- [Ionic v8](https://ionicframework.com/)
- [Angular v18](https://angular.io/)
- [Firebase cloudstore v10](https://firebase.google.com/)

## ๐ŸŒณ Project Structure

```
todo/
โ”œโ”€โ”€ src
โ”‚ย ย  โ”œโ”€โ”€ app
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ app.component.html
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ app.component.scss
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ app.component.spec.ts
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ app.component.ts
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ app.routes.ts
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ core
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ domain
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ api
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos_api.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ exceptions
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ exceptions.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ model
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ category.model.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ json_map.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todo.model.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ language
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ language-switcher.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ language.service.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ model
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ language.model.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ settings
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ settings-dropdown.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ theme
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ theme-switcher.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ theme.service.ts
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ features
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ categories
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ data
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ infrastructure
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ local-storage-api
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ local.storage.categories.api.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ repository
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ categories-repository-impl.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ domain
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ infrastructure
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ categories_api.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ repository
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ categories_repository.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ presentation
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ category-list
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ category-list.page.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ category-list.service.ts
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ home
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ presentation
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ home.page.ts
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ data
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ infrastructure
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ local_storage
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ local.storage.todos.api.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ repository
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos-repository-impl.ts
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ domain
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ repository
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos_repository.ts
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ presentation
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ components
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ category-badge.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ category-filter.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ stats
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ stats.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ stats.service.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ todo-list-item
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ todo-list-item.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todo-list-item.service.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ todos-overview-filter-button.component.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos-overview-options-button.component.ts
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ edit-todo
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ edit-todo.page.ts
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ edit-todo.service.ts
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos-overview
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ todos-overview.page.ts
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ todos-overview.service.ts
โ”‚ย ย  โ”œโ”€โ”€ app.config.ts
โ”‚ย ย  โ”œโ”€โ”€ assets
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ i18n
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ en.json
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ es.json
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ icon
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ favicon.png
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ shapes.svg
โ”‚ย ย  โ”œโ”€โ”€ environments
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ environment.prod.ts
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ environment.ts
โ”‚ย ย  โ”œโ”€โ”€ global.scss
โ”‚ย ย  โ”œโ”€โ”€ index.html
โ”‚ย ย  โ”œโ”€โ”€ main.ts
โ”‚ย ย  โ”œโ”€โ”€ polyfills.ts
โ”‚ย ย  โ”œโ”€โ”€ test.ts
โ”‚ย ย  โ”œโ”€โ”€ theme
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ variables.scss
โ”‚ย ย  โ””โ”€โ”€ zone-flags.ts
โ”œโ”€โ”€ tsconfig.app.json
โ”œโ”€โ”€ tsconfig.json
โ””โ”€โ”€ tsconfig.spec.json
```

- `todo.model.ts`: Defines the `Todo` interface
- `todos.api.ts`: Contains the abstract `TodosApi` class
- `local-storage-todos.api.ts`: Implements `TodosApi` using local storage

## :floppy_disk: Setup / Installation

1. Clone the repository:

```shell
git clone https://github.com/tech-andgar/todo-api-project.git
```

2. Navigate to the project directory:

```shell
cd todo-api-project
```

3. Install dependencies:

```shell
pnpm i
```

or

```shell
yarn i
```

or

```shell
npm i
```

4. Add firebase access credentials in:

`environment.ts`

5. Run the development server on _localhost://8100_:

``` shell
ionic serve
```

6. Create build artifacts in `www` folder:

``` shell
npm run build
```

## Usage

To use the Todo API in your Angular application, inject the `TodosApi` service into your component or service:

```typescript
import { Component } from '@angular/core';
import { TodosApi } from './path-to-todos-api';
import { Todo } from './path-to-todo-model';

@Component({
selector: 'app-todo-list',
template: '...'
})
export class TodoListComponent {
todos: Todo[] = [];

constructor(private todosApi: TodosApi) {
this.todosApi.getTodos().subscribe(todos => this.todos = todos);
}

addTodo(todo: Todo) {
this.todosApi.saveTodo(todo).subscribe(success => {
if (success) {
console.log('Todo added successfully');
}
});
}
}
```

## Key Components

1. `core/domain/model/todo.model.ts`: Defines the `Todo` interface.
2. `core/api/todos.api.ts`: Abstract class defining the API for managing todos.
3. `data/api/local-storage-todos.api.ts`: Concrete implementation of `TodosApi` using local storage.
4. `features/todo/`: Contains components, services, and module for the todo feature.

## ๐Ÿ“š API Reference

### TodosApi

The `TodosApi` abstract class provides the following methods:

#### Todo Retrieval Methods

- `getTodos(): Observable`
- Provides an Observable of all todos.

- `getTodo(todoId: string): Observable`
- Retrieves a todo by its ID.

#### Todo Modification Methods

- `saveTodo(todo: Todo): Observable`
- Saves a todo. If a todo with the same ID already exists, it will be replaced.

- `saveTodoAt(todo: Todo, index: number | null): Observable`
- Saves a todo at a specified index. If a todo with the same ID already exists, it will be replaced.

#### Todo Deletion Methods

- `deleteTodo(id: string): Observable`
- Deletes the todo with the given ID.

#### Batch Operations Methods

- `clearCompleted(): Observable`
- Deletes all completed todos.

- `completeAll(isCompleted: boolean): Observable`
- Sets the `isCompleted` state of all todos to the given value.

#### Resource Management Methods

- `close(): Observable`
- Closes the API client and frees up any resources.

## :computer: Code Examples - Implementation Details

### LocalStorageTodosApi

The `LocalStorageTodosApi` class implements the `TodosApi` abstract class using browser's local storage for persistence. Key features include:

- Uses `BehaviorSubject` to manage the stream of todos
- Implements all abstract methods from `TodosApi`
- Persists todos to local storage after each operation
- Retrieves todos from local storage on initialization

Example of saving a todo:

```typescript
saveTodo(todo: Todo): Observable {
const todos = [...this.todoStreamController.value];
const todoIndex = todos.findIndex(t => t.id === todo.id);
if (todoIndex >= 0) {
todos[todoIndex] = todo;
} else {
todos.push(todo);
}

this.todoStreamController.next(todos);
localStorage.setItem(LocalStorageTodosApi.kTodosCollectionKey, JSON.stringify(todos));

return this.getTodo(todo.id).pipe(map(todo => !!todo));
}
```

## ๐Ÿงช Testing

To run the tests for this project:

```shell
ng test
```

We use Jasmine for unit testing and Karma as the test runner. Key areas to test include:

- Individual CRUD operations
- Batch operations
- Edge cases (e.g., deleting non-existent todos)
- Local storage persistence

## โš ๏ธ Performance Considerations

- The current implementation loads all todos into memory, which may not be optimal for large datasets.
- Consider implementing pagination or virtual scrolling for better performance with large lists.
- Local storage has limited capacity; for larger applications, consider using IndexedDB or a backend server.

## :clipboard: Status & To-do list

- Status: Working.
- To-do:
- [ ] Implementation Firestore
- [ ] Implementation Feature Flag
- [ ] Testing

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the project
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

## :file_folder: License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.

## :envelope: Contact

Repo created by [TECH-ANDGAR](https://github.com/tech-andgar), email: