Membuat to do list menggunakan node.js

Membuat Aplikasi Todo List Menggunakan Node.js dan React Native

Pada proyek ini saya membuat sebuah aplikasi Todo List menggunakan React Native dengan dukungan Node.js sebagai lingkungan pengembangan. Aplikasi ini bertujuan untuk membantu pengguna dalam mencatat, mengelola, dan memantau daftar tugas agar aktivitas sehari-hari menjadi lebih teratur.

Aplikasi memiliki beberapa fitur utama, yaitu menambahkan tugas baru, menampilkan daftar tugas, mengedit tugas, menghapus tugas, serta menampilkan jumlah total tugas dan jumlah tugas yang telah diselesaikan. Seluruh data tugas ditampilkan menggunakan komponen FlatList, sehingga daftar tugas dapat ditampilkan dengan rapi dan efisien.

Dalam proses pembuatannya, saya menggunakan Node.js sebagai runtime JavaScript dan npm (Node Package Manager) untuk mengelola berbagai package yang diperlukan. Sementara itu, React Native digunakan untuk membangun antarmuka aplikasi sehingga dapat dijalankan pada perangkat mobile.

Dari proyek ini saya mempelajari cara mengelola data menggunakan useState, membuat komponen antarmuka yang interaktif, serta menerapkan operasi CRUD (Create, Read, Update, Delete) pada aplikasi Todo List. Selain itu, saya juga belajar bagaimana menyusun tampilan aplikasi agar terlihat lebih menarik dan mudah digunakan.

Secara keseluruhan, aplikasi Todo List ini berhasil memenuhi fungsi utamanya sebagai media untuk mengelola daftar tugas. Meskipun masih sederhana, proyek ini menjadi langkah awal yang baik untuk memahami pengembangan aplikasi mobile menggunakan Node.js dan React Native, serta dapat dikembangkan lebih lanjut dengan fitur seperti penyimpanan database, pengingat tugas, dan autentikasi pengguna.

Ini Gambarnya takutnya pengen lihat :


Ini sekalian codenya juga :

import React, { useState } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableOpacity,
  FlatList,
  Keyboard,
  Alert,
} from 'react-native';
import { StatusBar } from 'expo-status-bar';

export default function App() {
  const [task, setTask] = useState('');
  const [tasks, setTasks] = useState([
    { id: '1', text: '📚 Belajar React Native', completed: false },
    { id: '2', text: '💻 Buat Aplikasi Todo List', completed: false },
    { id: '3', text: '🎯 Selesaikan Project', completed: false },
  ]);
  const [editingId, setEditingId] = useState(null);

  // Fungsi untuk menambah tugas
  const addTask = () => {
    if (task.trim().length === 0) {
      Alert.alert('⚠️', 'Tugas tidak boleh kosong!');
      return;
    }

    if (editingId) {
      // Mode Edit
      setTasks(
        tasks.map((item) =>
          item.id === editingId ? { ...item, text: task.trim() } : item
        )
      );
      setEditingId(null);
    } else {
      // Mode Tambah
      const newTask = {
        id: Date.now().toString(),
        text: task.trim(),
        completed: false,
      };
      setTasks([...tasks, newTask]);
    }
    setTask('');
    Keyboard.dismiss();
  };

  // Fungsi untuk menghapus tugas
  const deleteTask = (id) => {
    Alert.alert(
      '🗑️ Hapus Tugas',
      'Yakin mau hapus tugas ini?',
      [
        { text: 'Batal', style: 'cancel' },
        {
          text: 'Hapus',
          style: 'destructive',
          onPress: () => setTasks(tasks.filter((item) => item.id !== id)),
        },
      ]
    );
  };

  // Fungsi untuk toggle selesai/belum
  const toggleComplete = (id) => {
    setTasks(
      tasks.map((item) =>
        item.id === id ? { ...item, completed: !item.completed } : item
      )
    );
  };

  // Fungsi untuk edit
  const startEdit = (item) => {
    setTask(item.text);
    setEditingId(item.id);
  };

  // Render item tugas
  const renderTask = ({ item }) => (
    <TouchableOpacity
      style={[
        styles.taskItem,
        item.completed && styles.taskItemCompleted,
      ]}
      onPress={() => toggleComplete(item.id)}
      activeOpacity={0.7}
    >
      <View style={styles.taskLeft}>
        <Text style={[styles.taskText, item.completed && styles.taskTextCompleted]}>
          {item.text}
        </Text>
      </View>

      <View style={styles.taskRight}>
        {!item.completed && (
          <TouchableOpacity
            onPress={() => startEdit(item)}
            style={styles.editButton}
          >
            <Text style={styles.editText}>✏️</Text>
          </TouchableOpacity>
        )}
        <TouchableOpacity
          onPress={() => deleteTask(item.id)}
          style={styles.deleteButton}
        >
          <Text style={styles.deleteText}>🗑️</Text>
        </TouchableOpacity>
      </View>
    </TouchableOpacity>
  );

  // Statistik
  const totalTasks = tasks.length;
  const completedTasks = tasks.filter((item) => item.completed).length;

  return (
    <View style={styles.container}>
      <StatusBar style="light" />

      {/* Header */}
      <View style={styles.header}>
        <Text style={styles.headerTitle}>📋 Todo List</Text>
        <Text style={styles.headerSubtitle}>
          {completedTasks} dari {totalTasks} selesai
        </Text>
        <View style={styles.progressBar}>
          <View
            style={[
              styles.progressFill,
              { width: totalTasks > 0 ? `${(completedTasks / totalTasks) * 100}%` : '0%' },
            ]}
          />
        </View>
      </View>

      {/* Form Input */}
      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          placeholder="✍️ Tambahkan tugas..."
          placeholderTextColor="#999"
          value={task}
          onChangeText={setTask}
          onSubmitEditing={addTask}
        />
        <TouchableOpacity
          style={[styles.addButton, !task.trim() && styles.addButtonDisabled]}
          onPress={addTask}
          disabled={!task.trim()}
        >
          <Text style={styles.addButtonText}>
            {editingId ? '🔄 Update' : '➕ Tambah'}
          </Text>
        </TouchableOpacity>
      </View>

      {/* Daftar Tugas */}
      {tasks.length === 0 ? (
        <View style={styles.emptyContainer}>
          <Text style={styles.emptyEmoji}>🎉</Text>
          <Text style={styles.emptyText}>Belum ada tugas!</Text>
          <Text style={styles.emptySubText}>Tambahkan tugas pertama kamu</Text>
        </View>
      ) : (
        <FlatList
          data={tasks}
          renderItem={renderTask}
          keyExtractor={(item) => item.id}
          contentContainerStyle={styles.listContainer}
          showsVerticalScrollIndicator={false}
        />
      )}

      {/* Footer */}
      <View style={styles.footer}>
        <Text style={styles.footerText}>
          {totalTasks} tugas • {completedTasks} selesai
        </Text>
      </View>
    </View>
  );
}

// ==================== STYLING ====================

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5F7FA',
    paddingTop: 50,
  },

  // HEADER
  header: {
    paddingHorizontal: 20,
    paddingBottom: 20,
    backgroundColor: '#6C63FF',
    borderBottomLeftRadius: 30,
    borderBottomRightRadius: 30,
    paddingTop: 20,
  },
  headerTitle: {
    fontSize: 28,
    fontWeight: 'bold',
    color: '#fff',
    marginBottom: 5,
  },
  headerSubtitle: {
    fontSize: 14,
    color: 'rgba(255,255,255,0.8)',
    marginBottom: 10,
  },
  progressBar: {
    height: 6,
    backgroundColor: 'rgba(255,255,255,0.3)',
    borderRadius: 10,
    overflow: 'hidden',
  },
  progressFill: {
    height: '100%',
    backgroundColor: '#FFD700',
    borderRadius: 10,
  },

  // INPUT
  inputContainer: {
    flexDirection: 'row',
    paddingHorizontal: 20,
    marginTop: -20,
    marginBottom: 15,
  },
  input: {
    flex: 1,
    backgroundColor: '#fff',
    paddingHorizontal: 18,
    paddingVertical: 14,
    borderRadius: 15,
    fontSize: 16,
    color: '#333',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  addButton: {
    backgroundColor: '#6C63FF',
    paddingHorizontal: 20,
    paddingVertical: 14,
    borderRadius: 15,
    marginLeft: 10,
    justifyContent: 'center',
    shadowColor: '#6C63FF',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 3,
  },
  addButtonDisabled: {
    backgroundColor: '#A9A9A9',
    shadowOpacity: 0,
  },
  addButtonText: {
    color: '#fff',
    fontWeight: 'bold',
    fontSize: 14,
  },

  // LIST
  listContainer: {
    paddingHorizontal: 20,
    paddingBottom: 100,
  },

  // TASK ITEM
  taskItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: '#fff',
    padding: 16,
    borderRadius: 15,
    marginBottom: 10,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
    elevation: 2,
  },
  taskItemCompleted: {
    backgroundColor: '#E8F5E9',
    opacity: 0.8,
  },
  taskLeft: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
  },
  taskText: {
    fontSize: 16,
    color: '#333',
    flex: 1,
  },
  taskTextCompleted: {
    textDecorationLine: 'line-through',
    color: '#888',
  },
  taskRight: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  editButton: {
    marginRight: 10,
    padding: 5,
  },
  editText: {
    fontSize: 18,
  },
  deleteButton: {
    padding: 5,
  },
  deleteText: {
    fontSize: 18,
  },

  // EMPTY STATE
  emptyContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    paddingHorizontal: 20,
  },
  emptyEmoji: {
    fontSize: 60,
    marginBottom: 15,
  },
  emptyText: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#333',
  },
  emptySubText: {
    fontSize: 14,
    color: '#999',
    marginTop: 5,
  },

  // FOOTER
  footer: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: '#fff',
    paddingVertical: 12,
    alignItems: 'center',
    borderTopWidth: 1,
    borderTopColor: '#eee',
  },
  footerText: {
    color: '#888',
    fontSize: 12,
  },
});

Kesimpulan

Aplikasi Todo List yang dibuat menggunakan React Native dengan dukungan Node.js berhasil membantu pengguna dalam mencatat dan mengelola daftar tugas. Melalui proyek ini, saya mempelajari dasar-dasar pengembangan aplikasi mobile, seperti pengelolaan data, pembuatan antarmuka, dan penerapan fitur CRUD (Create, Read, Update, Delete). Proyek ini juga menjadi bekal untuk mengembangkan aplikasi yang lebih lengkap di masa mendatang.

Oleh : Rian Rama Romansah

Komentar

Postingan populer dari blog ini

Membangun Aplikasi Kuliner Nusantara dengan Login dan Navigasi Multi-Halaman

Materi Widget

2 ARTIKEL PENGEMBANGAN GIM