diff --git a/data/db.sql b/data/db.sql
index 00e019d946752a5bd9d1eeb5ae13c1873c3c2ba7..2958af2044dc5bb7075526ad775d7fb3b395696d 100644
--- a/data/db.sql
+++ b/data/db.sql
@@ -33,17 +33,17 @@ DROP TABLE IF EXISTS `acara`;
 CREATE TABLE `acara` (
   `id_acara` int(11) NOT NULL AUTO_INCREMENT,
   `nama_acara` varchar(255) NOT NULL,
-  `video_introduksi` varchar(255) DEFAULT NULL,
-  `syarat_pendaftaran` text DEFAULT NULL,
-  `kuota_pendaftar` int(11) DEFAULT NULL,
-  `deskripsi` text DEFAULT NULL,
+  `video_introduksi` varchar(255) DEFAULT "" NOT NULL,
+  `syarat_pendaftaran` text DEFAULT "" NOT NULL,
+  `kuota_pendaftar` int(11) DEFAULT 0 NOT NULL,
+  `deskripsi` text DEFAULT "" NOT NULL,
   `waktu` datetime NOT NULL,
-  `harga` int(11) DEFAULT NULL,
-  `link` varchar(255) DEFAULT NULL,
+  `harga` int(11) DEFAULT 0 NOT NULL,
+  `link` varchar(255) DEFAULT "" NOT NULL,
   `id_penyelenggara` int(11) NOT NULL,
   PRIMARY KEY (`id_acara`),
   KEY `fk_penyelenggara_acara` (`id_penyelenggara`),
-  CONSTRAINT `fk_penyelenggara_acara` FOREIGN KEY (`id_penyelenggara`) REFERENCES `penyelenggara` (`id_penyelenggara`)
+  CONSTRAINT `fk_penyelenggara_acara` FOREIGN KEY (`id_penyelenggara`) REFERENCES `penyelenggara` (`id_penyelenggara`) ON DELETE RESTRICT ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
@@ -66,10 +66,10 @@ DROP TABLE IF EXISTS `foto_acara`;
 CREATE TABLE `foto_acara` (
   `id_acara` int(11) NOT NULL,
   `id_foto` int(11) NOT NULL AUTO_INCREMENT,
-  `foto` blob DEFAULT NULL,
+  `foto` mediumblob DEFAULT NULL,
   PRIMARY KEY (`id_foto`),
   KEY `fk_foto_acara` (`id_acara`),
-  CONSTRAINT `fk_foto_acara` FOREIGN KEY (`id_acara`) REFERENCES `acara` (`id_acara`)
+  CONSTRAINT `fk_foto_acara` FOREIGN KEY (`id_acara`) REFERENCES `acara` (`id_acara`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
@@ -116,7 +116,7 @@ CREATE TABLE `kategori_acara` (
   `id_acara` int(11) NOT NULL,
   `nama_kategori` varchar(255) NOT NULL,
   PRIMARY KEY (`id_acara`,`nama_kategori`),
-  CONSTRAINT `fk_kategori_acara` FOREIGN KEY (`id_acara`) REFERENCES `acara` (`id_acara`)
+  CONSTRAINT `fk_kategori_acara` FOREIGN KEY (`id_acara`) REFERENCES `acara` (`id_acara`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
@@ -140,7 +140,7 @@ CREATE TABLE `kategori_member` (
   `id_member` int(11) NOT NULL,
   `nama_kategori` varchar(255) NOT NULL,
   PRIMARY KEY (`id_member`,`nama_kategori`),
-  CONSTRAINT `fk_kategori_member` FOREIGN KEY (`id_member`) REFERENCES `member` (`id_member`)
+  CONSTRAINT `fk_kategori_member` FOREIGN KEY (`id_member`) REFERENCES `member` (`id_member`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
@@ -164,7 +164,7 @@ CREATE TABLE `member` (
   `id_member` int(11) NOT NULL AUTO_INCREMENT,
   `nama_depan` varchar(255) NOT NULL,
   `nama_belakang` varchar(255) NOT NULL,
-  `foto_profil` blob DEFAULT NULL,
+  `foto_profil` mediumblob DEFAULT NULL,
   `email` varchar(255) NOT NULL,
   `password` varchar(255) NOT NULL,
   `nomor_telepon` varchar(15) DEFAULT NULL,
@@ -197,8 +197,8 @@ CREATE TABLE `mengikuti` (
   `jumlah` int(11) DEFAULT NULL,
   KEY `fk_member_mengikuti` (`id_member`),
   KEY `fk_mengikuti_acara` (`id_acara`),
-  CONSTRAINT `fk_member_mengikuti` FOREIGN KEY (`id_member`) REFERENCES `member` (`id_member`),
-  CONSTRAINT `fk_mengikuti_acara` FOREIGN KEY (`id_acara`) REFERENCES `acara` (`id_acara`)
+  CONSTRAINT `fk_member_mengikuti` FOREIGN KEY (`id_member`) REFERENCES `member` (`id_member`) ON UPDATE CASCADE ON DELETE RESTRICT,
+  CONSTRAINT `fk_mengikuti_acara` FOREIGN KEY (`id_acara`) REFERENCES `acara` (`id_acara`) ON UPDATE CASCADE ON DELETE RESTRICT
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
@@ -222,7 +222,7 @@ CREATE TABLE `penyelenggara` (
   `id_penyelenggara` int(11) NOT NULL AUTO_INCREMENT,
   `nama_organisasi` varchar(255) NOT NULL,
   `penanggung_jawab` varchar(255) NOT NULL,
-  `foto_profil` blob DEFAULT NULL,
+  `foto_profil` mediumblob DEFAULT NULL,
   `video_introduksi` varchar(255) DEFAULT NULL,
   `deskripsi` text DEFAULT NULL,
   `email` varchar(255) NOT NULL,
diff --git a/makefile b/makefile
index 241d222e89334be4b804f998ae46ec5d36594ffa..4bdbcd8d0e1b591dc37490f55b8a30f096e194bc 100644
--- a/makefile
+++ b/makefile
@@ -10,4 +10,4 @@ run: test
 	$(PY) $(main_dir)/$(main_py)
 
 test:
-	$(PY) -m pytest src/*
\ No newline at end of file
+	$(PY) -m pytest src/test/*
diff --git a/src/app/main.py b/src/app/main.py
index c8f6cd83486e7bf471625d03ebc3cd152bbac56c..acf30ecad3209498899210aca70e5283ab7611fc 100644
--- a/src/app/main.py
+++ b/src/app/main.py
@@ -1,13 +1,42 @@
 from app.ui.main_window_ui import *
 from app.db import init_db
+import datetime
+import sys
 
+from PyQt5.QtWidgets import (
+    QApplication, QDialog, QMainWindow, QMessageBox
+)
+from PyQt5.uic import loadUi
+
+from app.ui import main_window_ui
 if __name__ == '__main__':
     conn = init_db()
-    cur = conn.cursor()
+
+    windows = []
 
     app = QtWidgets.QApplication(sys.argv)
     YesManagement = QtWidgets.QMainWindow()
-    ui = Ui_YesManagement(conn)
+    ui = Ui_YesManagement(conn, windows)
     ui.setupUi(YesManagement)
     YesManagement.show()
-    sys.exit(app.exec_())
\ No newline at end of file
+    sys.exit(app.exec_())
+
+
+    # app = QApplication(sys.argv)
+    # main_window_ui.Ui_YesManagement(conn)
+    # sys.exit(app.exec())
+
+    # cur = conn.cursor()
+    # ###################
+    # # BUAT DETAIL ACARA
+    # # Ini tinggal diganti aja
+    # PATH = "./ui/assets/"
+    # currIDUser = 2
+    # currIDAcara = 1
+    # isMember = True
+
+    # # execute SQL query
+    # # lengkapnya: https://mariadb.com/resources/blog/how-to-connect-python-programs-to-mariadb/
+    # #################
+
+    conn.close()
diff --git a/src/app/modules/linimasa.py b/src/app/modules/linimasa.py
index 8cb1754a0c4accd1d5a8891fd48ff2852deaf993..c175be03bd89f62d0e3264e5596d6b62e2ae6f1f 100644
--- a/src/app/modules/linimasa.py
+++ b/src/app/modules/linimasa.py
@@ -1,83 +1,89 @@
-import mariadb
+"""Modul linimasa"""
 
-def linimasa(conn, extraFilter, params=None):
-  """Fungsi untuk mengembalikan list acara untuk linimasa
-  Parameters
-  ----------
-  conn: connection
-    Connection ke database yang digunakan
-  extraFilter: string
-    klausa WHERE untuk query yang akan dilakukan
-  params: list (optional)
-    List parameter untuk prepared statement
-  Returns
-  -------
-  list (id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu, list_kategori)
-  """
-  cursor = conn.cursor()
-  cursor.execute(\
-    f'SELECT\
-      id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu\
-      FROM acara'+\
-      extraFilter, params
-  )
+def linimasa(conn, extra_filter, params=None):
+    """Fungsi untuk mengembalikan list acara untuk linimasa
+    Parameters
+    ----------
+    conn: connection
+        Connection ke database yang digunakan
+    extraFilter: string
+        klausa WHERE untuk query yang akan dilakukan
+    params: list (optional)
+        List parameter untuk prepared statement
+    Returns
+    -------
+    list (id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu, list_kategori)
+    """
 
-  ret = []
-  for res in cursor.fetchall():
-    cursor.execute('SELECT nama_kategori FROM kategori_acara WHERE id_acara = ?', (res[0],))
-    kategori = cursor.fetchall()
-    ret.append((*res, list(*kategori)))
-  return ret
+    cursor = conn.cursor()
+    cursor.execute(\
+        'SELECT\
+            id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu\
+            FROM acara'+\
+            extra_filter, params
+    )
 
-def linimasaPengguna(conn, kategFilter=[], search=""):
-  """Fungsi untuk mengambil acara pada linimasa pengguna
-  Parameters
-  ----------
-  conn : connection
-    Connection ke database yang digunakan
-  kategFilter: list
-    list filter yang digunakan
-  search: string
-    kata kunci pencarian
-  Returns
-  -------
-  list (id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu, list_kategori)
-  """
-  
-  # setup parameter untuk klausa WHERE
-  where = ""
-  params = []
-  if len(kategFilter) != 0:
-    where += " WHERE id_acara in\
-      (SELECT id_acara FROM kategori_acara WHERE kategori_acara IN\
-      (" + ",".join(["?" for _ in range(len(kategFilter))]) + ")"
-    params.extend(kategFilter)
-  if search != '':
-    where += ' WHERE' if where == '' else ''
-    where += ' nama_acara LIKE ?'
-    params.append(search)
-  
-  # gunakan fungsi pembantu linimasa
-  return linimasa(conn, where)
+    ret = []
+    for res in cursor.fetchall():
+        cursor.execute('SELECT nama_kategori FROM kategori_acara WHERE id_acara = ?', (res[0],))
+        kategori = cursor.fetchall()
+        ret.append((*res, [k[0] for k in kategori]))
+    return ret
 
-def linimasaPenyelenggara(conn, endedFilter=None):
-  """Fungsi untuk mengambil acara pada linimasa penyelenggara
-  Parameters
-  ----------
-  conn: connection
-    Connection ke database yang digunakan
-  endedFilter: bool (optional)
-    Filter yang digunakan untuk memfilter linimasa: sudah apakah acara yang
-    ditampilkan yang sudah berakhir (`True`) atau belum (`False`)
-  Returns
-  -------
-  list (id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu, list_kategori)
-  """
+def linimasa_pengguna(conn, kateg_filter=None, search=""):
+    """Fungsi untuk mengambil acara pada linimasa pengguna
+    Parameters
+    ----------
+    conn : connection
+        Connection ke database yang digunakan
+    kateg_filter: list
+        list filter yang digunakan
+    search: string
+        kata kunci pencarian
+    Returns
+    -------
+    list (id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu, list_kategori)
+    """
 
-  # setup parameter untuk klausa WHERE
-  where = ""
-  if endedFilter is not None:
-    where = f' WHERE waktu {"<" if endedFilter else ">="} NOW()'
-  
-  # gunakan fungsi pembantu linimasa
-  return linimasa(conn, where)
\ No newline at end of file
+    # setup parameter untuk klausa WHERE
+    where = ""
+    params = []
+    if kateg_filter is not None:
+        where += " WHERE id_acara in\
+            (SELECT id_acara FROM kategori_acara WHERE nama_kategori IN\
+            (" + ",".join(["?" for _ in range(len(kateg_filter))]) + "))"
+        params.extend(kateg_filter)
+    if search != '':
+        where += ' WHERE' if where == '' else ' AND'
+        where += ' nama_acara LIKE ?'
+        params.append(search)
+
+    # gunakan fungsi pembantu linimasa
+    return linimasa(conn, where, params)
+
+def linimasa_penyelenggara(conn, ended_filter=None, search=""):
+    """Fungsi untuk mengambil acara pada linimasa penyelenggara
+    Parameters
+    ----------
+    conn: connection
+        Connection ke database yang digunakan
+    ended_filter: bool (optional)
+        Filter yang digunakan untuk memfilter linimasa: sudah apakah acara yang
+        ditampilkan yang sudah berakhir (`True`) atau belum (`False`)
+    Returns
+    -------
+    list (id_acara, nama_acara, kuota_pendaftar, deskripsi, waktu, list_kategori)
+    """
+
+    # setup parameter untuk klausa WHERE
+    where = ""
+    params = None
+    if ended_filter is not None:
+        where = f' WHERE waktu {"<" if ended_filter else ">="} NOW()'
+    if search != '':
+        where += ' AND' if where != '' else ' WHERE'
+        where += ' nama_acara LIKE ?'
+        params = [search] 
+
+    # gunakan fungsi pembantu linimasa
+    return linimasa(conn, where, params)
diff --git a/src/app/modules/pesan.py b/src/app/modules/pesan.py
index 51fca5e7c6a08b7e289be027a78da86390778a8f..0bab5f99f2d60753024521f43eb2a8f7e396c6c8 100644
--- a/src/app/modules/pesan.py
+++ b/src/app/modules/pesan.py
@@ -31,10 +31,10 @@ def pesanTiket(conn,idAcara,idMember,jml):
         memberAcara.append(val[0])
 
     if (jml <= kuota-kuotaPesan and not idMember in memberAcara):
-        print(kuota-kuotaPesan)
-        print(jml)
-        # cur.execute("INSERT INTO mengikuti(id_member,id_acara,order_valid,jumlah) VALUES (%s,%s,%s,%s)",(idMember,idAcara,1,jml))
-        # cur.execute("SELECT * FROM mengikuti")
+        # print(kuota-kuotaPesan)
+        # print(jml)
+        cur.execute("INSERT INTO mengikuti(id_member,id_acara,order_valid,jumlah) VALUES (%s,%s,%s,%s)",(idMember,idAcara,1,jml))
+        conn.commit()
         # for val in cur:
         #     print(val)
         return True
diff --git a/src/app/modules/tambahAcara.py b/src/app/modules/tambahAcara.py
deleted file mode 100644
index 7508727e2829063ae361e7a6a29b101a2229d500..0000000000000000000000000000000000000000
--- a/src/app/modules/tambahAcara.py
+++ /dev/null
@@ -1,117 +0,0 @@
-'''
-Modul untuk operasi edit dan tambah acara
-'''
-from datetime import datetime
-from app.db import init_db
-import mariadb
-
-
-def tambah_acara(id_penyelenggara,
-                 nama_acara,
-                 kuota_pendaftar,
-                 waktu,
-                 harga,
-                 conn,
-                 link=None,
-                 deskripsi=None,
-                 syarat=None,
-                 video_introduksi=None,
-                 id_acara=None) -> bool:
-    ''' Fungsi untuk menambahkan sebuah acara baru ke database atau mengubah
-    keterangan acara jika sudah ada
-    Parameters
-    ----------
-    id_penyelenggara : int
-        id penyelenggara yang melaksanakan acara
-    nama_acara : str
-        nama acara
-    kuota_pendaftar : int
-        kuota pendaftar acara
-    waktu : datetime | str
-        waktu acara diadakan. Jika str akan otomatis diubah ke datetime, str
-        dalam format YYYY-MM-DD HH:MM:SS
-    harga : int
-        harga tiket acara
-    conn : mariadb._mariadb.connection
-        koneksi ke database
-    video_introduksi : str (optional)
-        link ke video penyelenggara
-    syarat : str (optional)
-        syarat acara
-    deskripsi : str (optional)
-        deskripsi acara
-    link : str (optional)
-        URL ke tempat pertemuan acara
-    id_acara : int (optional)
-        id acara, nilai default adalah None. Jika tidak bukan None artinya
-        mengubah acara.
-    Returns
-    -------
-    True jika berhasil menambahkan atau memperbarui acara, selain itu False
-    '''
-    if isinstance(waktu, str):
-        try:
-            waktu = datetime.strptime(waktu, "%Y-%m-%d %H:%M:%S")
-        except ValueError:
-            return False
-
-    # conn = init_db()
-    cur = conn.cursor()
-
-    if id_acara == None:
-        try:
-            cur.execute(
-                '''INSERT INTO acara
-                        (nama_acara,
-                        video_introduksi,
-                        syarat_pendaftaran,
-                        kuota_pendaftar,
-                        deskripsi,
-                        waktu,
-                        harga,
-                        link,
-                        id_penyelenggara)
-                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)''', (
-                    nama_acara,
-                    video_introduksi,
-                    syarat,
-                    kuota_pendaftar,
-                    deskripsi,
-                    waktu,
-                    harga,
-                    link,
-                    id_penyelenggara
-                ))
-            conn.commit()
-            return True
-        except mariadb.Error:
-            return False
-    else:
-        try:
-            cur.execute(
-                '''UPDATE acara
-                    SET
-                        nama_acara = ?,
-                        video_introduksi = ?,
-                        syarat_pendaftaran = ?,
-                        kuota_pendaftar = ?,
-                        deskripsi = ?,
-                        waktu = ?,
-                        harga = ?,
-                        link = ?
-                    WHERE id_acara = ?''', (
-                    nama_acara,
-                    video_introduksi,
-                    syarat,
-                    kuota_pendaftar,
-                    deskripsi,
-                    waktu,
-                    harga,
-                    link,
-                    id_acara
-                 ))
-            conn.commit()
-            return True
-        except mariadb.Error as e:
-            print(e)
-            return False
diff --git a/src/app/modules/tambah_acara.py b/src/app/modules/tambah_acara.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9727c49a43f21ac2439c9e8f2f27ff5abf22de4
--- /dev/null
+++ b/src/app/modules/tambah_acara.py
@@ -0,0 +1,260 @@
+'''
+Modul untuk operasi edit dan tambah acara
+'''
+from datetime import datetime
+from app.db import init_db
+import mariadb
+
+def __add_foto(photos, id_acara, cur):
+    '''
+    Fungsi untuk menambahkan foto-foto ke database
+
+    Parameters
+    ----------
+    photos : list[bytes]
+    path ke foto-foto yang ingin ditambahkan
+    nama_acara : str
+    nama acara
+    id_acara : int
+    id acara
+    cur : cursor
+    cursor koneksi ke database
+
+    Throws
+    ------
+    mariadb.Error
+    '''
+    # Foto-foto sebelumnya dikirim bersamaan array photos
+    cur.execute('''DELETE FROM foto_acara WHERE id_acara = ?''', (id_acara,))
+    # Bikin file gambar dan masukin ke database
+    for foto in photos:
+        cur.execute('''
+                INSERT INTO foto_acara (id_acara, foto)
+                VALUES (?, ?)''', (id_acara, foto))
+
+def __add_kategori(kategori, id_acara, cur):
+    '''
+    Fungsi untuk menambahkan kategori acara ke database
+
+    Parameters
+    ----------
+    kategori : list[bytes]
+    kategori-kategori acara
+    id_acara : int
+    id acara
+    cur : cursor
+    cursor koneksi ke database
+
+    Throws
+    ------
+    mariadb.Error
+    '''
+    cur.execute('''DELETE FROM kategori_acara WHERE id_acara = ?''', (id_acara,))
+    for kateg in kategori:
+        cur.execute('''INSERT INTO kategori_acara VALUES (?, ?)''', (id_acara, kateg))
+
+def remove_foto(id_acara, id_foto, conn) -> bool:
+    '''
+    Fungsi untuk menghapus sebuah foto acara
+
+    Parameters
+    ----------
+    id_acara : int
+    id acara
+    id_foto : int
+    id foto
+    conn : mariadb.connection
+    koneksi ke db
+
+    Returns
+    -------
+    True jika operasi berhasil (tidak menghasilkan error); selain itu False
+    '''
+    cur = conn.cursor()
+    try:
+        cur.execute('''DELETE FROM foto_acara WHERE id_acara = ? AND id_foto = ?''', (id_acara, id_foto))
+        conn.commit()
+        return True
+    except mariadb.Error as e:
+        print(e)
+        return False
+
+def remove_category(id_acara, kateg, conn) -> bool:
+    '''
+    Fungsi untuk menghapus kategori suatu acara
+
+    Parameters
+    ----------
+    id_acara : int
+    id acara
+    kateg : str
+    nama kategori
+    conn : mariadb.connection
+    koneksi ke db
+
+    Returns
+    -------
+    True jika operasi berhasil (tidak menghasilkan error); selain itu False
+    '''
+    cur = conn.cursor()
+    try:
+        cur.execute('''DELETE FROM kategori_acara WHERE id_acara = ? AND nama_kategori = ?''', (id_acara, kateg))
+        conn.commit()
+        return True
+    except mariadb.Error as e:
+        print(e)
+        return False
+
+def tambah_acara(id_penyelenggara,
+                 nama_acara,
+                 waktu,
+                 harga,
+                 kategori,
+                 conn,
+                 kuota_pendaftar=0,
+                 link="",
+                 deskripsi="",
+                 syarat="",
+                 video_introduksi="",
+                 foto=None,
+                 id_acara=None) -> bool:
+    '''
+    Fungsi untuk menambahkan sebuah acara baru ke database atau mengubah
+    keterangan acara jika sudah ada
+
+    Parameters
+    ----------
+    id_penyelenggara : int
+        id penyelenggara yang melaksanakan acara
+    nama_acara : str
+        nama acara
+    waktu : datetime | str
+        waktu acara diadakan. Jika str akan otomatis diubah ke datetime, str
+        dalam format YYYY-MM-DD HH:MM:SS
+    harga : int
+        harga tiket acara
+    kategori : list[str]
+        kategori-kategori acara
+    conn : mariadb._mariadb.connection
+        koneksi ke database
+    kuota_pendaftar : int (optional)
+        kuota pendaftar acara, kalo None artinya ga ada kuota
+    foto : list[bytes] (optional)
+        Sekumpulan path ke file foto
+    link : str (optional)
+        URL ke tempat pertemuan acara
+    deskripsi : str (optional)
+        deskripsi acara
+    syarat : str (optional)
+        syarat acara
+    video_introduksi : str (optional)
+        link ke video penyelenggara
+    id_acara : int (optional)
+        id acara, nilai default adalah None. Jika tidak bukan None artinya
+        mengubah acara.
+
+    Returns
+    -------
+    True jika berhasil menambahkan atau memperbarui acara, selain itu False
+    '''
+    if isinstance(waktu, str):
+        try:
+            waktu = datetime.strptime(waktu, "%Y-%m-%d %H:%M")
+        except ValueError:
+            return False
+
+    # conn = init_db()
+    cur = conn.cursor()
+
+    if len(kategori) == 0:
+        return False
+
+    if id_acara is None:
+        try:
+            cur.execute(
+                '''INSERT INTO acara
+                        (nama_acara,
+                        syarat_pendaftaran,
+                        kuota_pendaftar,
+                        deskripsi,
+                        waktu,
+                        harga,
+                        link,
+                        video_introduksi,
+                        id_penyelenggara)
+                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)''', (
+                    nama_acara,
+                    syarat,
+                    kuota_pendaftar,
+                    deskripsi,
+                    waktu,
+                    harga,
+                    link,
+                    video_introduksi,
+                    id_penyelenggara
+                ))
+
+            # Dapetin id acara
+            cur.execute('''SELECT id_acara FROM acara WHERE
+                    nama_acara = ? AND
+                    kuota_pendaftar = ? AND
+                    waktu  = ? AND
+                    harga = ? AND
+                    id_penyelenggara = ?''', (
+                        nama_acara,
+                        kuota_pendaftar,
+                        waktu,
+                        harga,
+                        id_penyelenggara
+                    ))
+            id_acara = cur.fetchone()[0]
+
+            # Tambah kategori
+            __add_kategori(kategori, id_acara, cur)
+
+            # Tambah foto
+            if foto is not None:
+                __add_foto(foto, id_acara, cur)
+
+            conn.commit()
+            return True
+        except mariadb.Error as e:
+            print(e)
+            return False
+    else:
+        try:
+            cur.execute(
+                '''UPDATE acara
+                    SET
+                        nama_acara = ?,
+                        syarat_pendaftaran = ?,
+                        kuota_pendaftar = ?,
+                        deskripsi = ?,
+                        waktu = ?,
+                        harga = ?,
+                        link = ?,
+                        video_introduksi = ?
+                    WHERE id_acara = ?''', (
+                    nama_acara,
+                    syarat,
+                    kuota_pendaftar,
+                    deskripsi,
+                    waktu,
+                    harga,
+                    link,
+                    video_introduksi,
+                    id_acara
+                 ))
+
+            # Tambah kategori
+            __add_kategori(kategori, id_acara, cur)
+
+            # Tambah foto
+            if foto is not None:
+                __add_foto(foto, id_acara, cur)
+
+            conn.commit()
+            return True
+        except mariadb.Error as e:
+            print(e)
+            return False
diff --git a/src/app/ui/assets/no-image-available.jpeg b/src/app/ui/assets/no-image-available.jpeg
new file mode 100755
index 0000000000000000000000000000000000000000..28b5b93702fdef2fc50fec7bb2fbad9fa7cc064a
Binary files /dev/null and b/src/app/ui/assets/no-image-available.jpeg differ
diff --git a/src/app/ui/auth_ui.py b/src/app/ui/auth_ui.py
index d389cd4116a3ce7d24a9808bf30ed2710112d9c9..0e67f31df670fffd88659a43d0b4b26600f2ca1d 100644
--- a/src/app/ui/auth_ui.py
+++ b/src/app/ui/auth_ui.py
@@ -11,6 +11,7 @@ import sys
 import re
 from PyQt5 import QtCore, QtGui, QtWidgets
 from app.modules.auth import *
+from app.ui.linimasa_ui import *
 from app.ui.util_ui import *
 
 EMAIL_REGEX = re.compile(r"[^@]+@[^@]+\.[^@]+")
@@ -122,8 +123,10 @@ class Ui_Register_Member_Dialog(object):
             callInfoDialog(str(err))
 
 class Ui_Login_Dialog(object):
-    def __init__(self, conn):
+    def __init__(self, conn, Window):
         self.conn = conn
+        self.linimasa = None
+        self.Window = Window
 
     def setupUi(self, Dialog):
         Dialog.setObjectName("Dialog")
@@ -185,9 +188,13 @@ class Ui_Login_Dialog(object):
 
     def okHandle(self):
         try:
-            login(self.conn, self.textEditEmail.toPlainText(), self.lineEditPassword.text())
+            (id, isPenyelenggara) = login(self.conn, self.textEditEmail.toPlainText(), self.lineEditPassword.text())
+            self.id = id
+            self.isPenyelenggara = isPenyelenggara
+
             callInfoDialog("Successfully logged in")
-            self.Dialog.close()
+
+            self.Dialog.accept()
         except Exception as err:
             callInfoDialog(str(err))
 
diff --git a/src/app/ui/detail_acara_window_ui.py b/src/app/ui/detail_acara_window_ui.py
new file mode 100644
index 0000000000000000000000000000000000000000..88469d9a9772848636131a8c57369b4fa1cbe254
--- /dev/null
+++ b/src/app/ui/detail_acara_window_ui.py
@@ -0,0 +1,420 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file './ui/main_window.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.2
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again.  Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+import datetime
+from app import db
+from app.modules import pesan
+from app.ui.linimasa_ui import *
+from app.ui.tambah_acara_ui import *
+
+class Ui_Dialog(object):
+    def setupUi(self, Dialog, first):
+        Dialog.setObjectName("Dialog")
+        Dialog.resize(311, 79)
+        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
+        self.buttonBox.setGeometry(QtCore.QRect(210, 10, 81, 241))
+        self.buttonBox.setOrientation(QtCore.Qt.Vertical)
+        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
+        self.buttonBox.setObjectName("buttonBox")
+        self.horizontalLayoutWidget = QtWidgets.QWidget(Dialog)
+        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 161, 41))
+        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
+        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
+        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout.setSpacing(80)
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
+        self.label.setObjectName("label")
+        self.horizontalLayout.addWidget(self.label)
+        self.spinBox = QtWidgets.QSpinBox(self.horizontalLayoutWidget)
+        self.spinBox.setObjectName("spinBox")
+        self.horizontalLayout.addWidget(self.spinBox)
+
+        if first: 
+            self.retranslateUi(Dialog)
+        else:
+            self.revalidationUi(Dialog)
+
+        self.buttonBox.accepted.connect(Dialog.accept)
+        self.buttonBox.rejected.connect(Dialog.reject)
+        QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+    def retranslateUi(self, Dialog):
+        _translate = QtCore.QCoreApplication.translate
+        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
+        self.label.setText(_translate("Dialog", "Jumlah"))
+    
+    def revalidationUi(self, Dialog):
+        _translate = QtCore.QCoreApplication.translate
+        Dialog.setWindowTitle(_translate("Dialog", "Pemesanan gagal"))
+        self.label.setText(_translate("Dialog", "Jumlah"))
+
+    def getQuantity(self):
+        return self.spinBox.value()
+
+class Ui_DetailAcaraWindow(object):
+    def setupUi(self, MainWindow, content, kategori, isMember):
+        MainWindow.setObjectName("MainWindow")
+        MainWindow.resize(813, 600)
+
+        self.idAcara = content[0]
+        self.idUser = content[11]
+        self.isMember = isMember
+
+        self.centralwidget = QtWidgets.QWidget(MainWindow)
+        self.centralwidget.setObjectName("centralwidget")
+
+        self.frame = QtWidgets.QFrame(self.centralwidget)
+        self.frame.setGeometry(QtCore.QRect(10, 310, 781, 261))
+        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
+        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
+        self.frame.setObjectName("frame")
+
+        self.textBrowser = QtWidgets.QTextBrowser(self.frame)
+        self.textBrowser.setGeometry(QtCore.QRect(10, 50, 256, 192))
+        self.textBrowser.setObjectName("textBrowser")
+
+        self.label_2 = QtWidgets.QLabel(self.frame)
+        self.label_2.setGeometry(QtCore.QRect(10, 10, 241, 31))
+        font = QtGui.QFont()
+        font.setPointSize(20)
+        self.label_2.setFont(font)
+        self.label_2.setObjectName("label_2")
+
+        self.scrollArea = QtWidgets.QScrollArea(self.frame)
+        self.scrollArea.setGeometry(QtCore.QRect(290, 10, 481, 231))
+        self.scrollArea.setWidgetResizable(True)
+        self.scrollArea.setObjectName("scrollArea")
+        self.scrollAreaWidgetContents = QtWidgets.QWidget()
+        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 479, 229))
+        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
+
+        self.textBrowser_2 = QtWidgets.QTextBrowser(self.scrollAreaWidgetContents)
+        self.textBrowser_2.setGeometry(QtCore.QRect(0, 0, 481, 231))
+        self.textBrowser_2.setObjectName("textBrowser_2")
+        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
+
+        self.idxPhoto = 0
+        self.photos = content[12]
+        self.label_5 = QtWidgets.QLabel(self.centralwidget)
+        if len(self.photos)!=0:
+            self.label_5.setGeometry(QtCore.QRect(230, 10, 311, 211))
+            self.label_5.setText("")
+            img = QtGui.QImage()
+            img.loadFromData(self.photos[self.idxPhoto])
+            self.label_5.setPixmap(QtGui.QPixmap.fromImage(img))
+            self.label_5.setScaledContents(True)
+            self.label_5.setObjectName("label_5")
+        else:
+            self.label_5.setGeometry(QtCore.QRect(340, 10, 311, 211))
+            font = QtGui.QFont()
+            font.setPointSize(16)
+            self.label_5.setText("No Photos")
+            self.label_5.setFont(font)
+
+        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
+        self.pushButton_2.setGeometry(QtCore.QRect(20, 10, 75, 23))
+        self.pushButton_2.setObjectName("pushButton_2")
+        self.pushButton_2.clicked.connect(self.back)
+
+        self.frame_2 = QtWidgets.QFrame(self.centralwidget)
+        self.frame_2.setGeometry(QtCore.QRect(10, 230, 781, 81))
+        self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
+        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
+        self.frame_2.setObjectName("frame_2")
+
+        self.pushButton = QtWidgets.QPushButton(self.frame_2)
+        self.pushButton.setGeometry(QtCore.QRect(660, 20, 111, 41))
+        self.pushButton.setObjectName("pushButton")
+        self.pushButton.clicked.connect(self.buttonHandler)
+
+        self.label_3 = QtWidgets.QLabel(self.frame_2)
+        self.label_3.setGeometry(QtCore.QRect(520, 22, 120, 20))
+        self.label_3.setObjectName("label_3")
+
+        self.label_4 = QtWidgets.QLabel(self.frame_2)
+        self.label_4.setGeometry(QtCore.QRect(540, 45, 90, 20))
+        self.label_4.setObjectName("label_4")
+
+        self.label = QtWidgets.QLabel(self.frame_2)
+        self.label.setGeometry(QtCore.QRect(10, 15, 211, 41))
+        font = QtGui.QFont()
+        font.setPointSize(18)
+        self.label.setFont(font)
+        self.label.setObjectName("label")
+
+        self.widget = QtWidgets.QWidget(self.frame_2)
+        self.widget.setGeometry(QtCore.QRect(240, 25, 281, 16))
+        self.widget.setObjectName("widget")
+
+        self.label_6 = QtWidgets.QLabel(self.widget)
+        self.label_6.setGeometry(QtCore.QRect(10, 0, 61, 16))
+        font = QtGui.QFont()
+        font.setPointSize(10)
+        self.label_6.setFont(font)
+        self.label_6.setObjectName("label_6")
+
+        self.label_7 = QtWidgets.QLabel(self.widget)
+        self.label_7.setGeometry(QtCore.QRect(80, 0, 61, 16))
+        font = QtGui.QFont()
+        font.setPointSize(10)
+        self.label_7.setFont(font)
+        self.label_7.setObjectName("label_7")
+
+        self.label_8 = QtWidgets.QLabel(self.widget)
+        self.label_8.setGeometry(QtCore.QRect(150, 0, 61, 16))
+        font = QtGui.QFont()
+        font.setPointSize(10)
+        self.label_8.setFont(font)
+        self.label_8.setObjectName("label_8")
+
+        self.label_9 = QtWidgets.QLabel(self.widget)
+        self.label_9.setGeometry(QtCore.QRect(220, 0, 61, 16))
+        font = QtGui.QFont()
+        font.setPointSize(10)
+        self.label_9.setFont(font)
+        self.label_9.setObjectName("label_9")
+
+        self.label_10 = QtWidgets.QLabel(self.frame_2)
+        self.label_10.setObjectName(u"label_10")
+        self.label_10.setGeometry(QtCore.QRect(10, 50, 161, 20))
+        font.setPointSize(12)
+        self.label_10.setFont(font)
+
+        self.label_11 = QtWidgets.QLabel(self.frame_2)
+        self.label_11.setObjectName(u"label_11")
+        self.label_11.setGeometry(QtCore.QRect(250, 45, 191, 16))
+
+        self.line = QtWidgets.QFrame(self.frame_2)
+        self.line.setObjectName(u"line")
+        self.line.setGeometry(QtCore.QRect(0, 70, 781, 16))
+        self.line.setFrameShape(QtWidgets.QFrame.HLine)
+        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
+
+        self.line_2 = QtWidgets.QFrame(self.frame_2)
+        self.line_2.setObjectName(u"line_2")
+        self.line_2.setGeometry(QtCore.QRect(0, 0, 781, 16))
+        self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
+        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
+
+        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
+        self.pushButton_3.setObjectName(u"pushButton_3")
+        self.pushButton_3.setGeometry(QtCore.QRect(580, 110, 75, 23))
+        self.pushButton_3.clicked.connect(self.nextPicture)
+
+        self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
+        self.pushButton_4.setObjectName(u"pushButton_4")
+        self.pushButton_4.setGeometry(QtCore.QRect(130, 110, 75, 23))
+        self.pushButton_4.clicked.connect(self.prevPicture)
+
+        self.widget.raise_()
+        self.pushButton.raise_()
+        self.label_3.raise_()
+        self.label_4.raise_()
+        self.label.raise_()
+        self.line.raise_()
+        self.line_2.raise_()
+
+        self.line_3 = QtWidgets.QFrame(self.centralwidget)
+        self.line_3.setObjectName(u"line_3")
+        self.line_3.setGeometry(QtCore.QRect(10, 560, 781, 16))
+        self.line_3.setFrameShape(QtWidgets.QFrame.HLine)
+        self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
+        MainWindow.setCentralWidget(self.centralwidget)
+        self.statusbar = QtWidgets.QStatusBar(MainWindow)
+        self.statusbar.setObjectName("statusbar")
+        MainWindow.setStatusBar(self.statusbar)
+
+        self.MainWindow = MainWindow
+
+        self.retranslateUi(MainWindow,content,kategori)
+        QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+    def retranslateUi(self, MainWindow, content, kategori):
+        _translate = QtCore.QCoreApplication.translate
+        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
+
+        syarat = content[3] if content[3] != None else "Tidak ada syarat"
+        htmlSyarat = '''<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n
+<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n
+p, li {0}\n
+</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n
+<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt;\">{val}</span></p></body></html>'''.format("{white-space: pre-wrap;}",val=syarat)
+        self.textBrowser.setHtml(_translate("MainWindow", htmlSyarat))
+        
+        self.label_2.setText(_translate("MainWindow", "Syarat"))
+        
+        desc = content[5] if content[5] != None else "-"
+        contact = content[9]
+        link = content[8] if content[8]!="" else "Belum ada"
+        htmlInfo = """<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n
+<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n
+p, li {0}\n
+</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n
+<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:20pt;\">Deskripsi</span></p>\n
+<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt;\">{descVal}</span></p>\n
+<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;\"><br /></p>\n
+<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;\"><br /></p>\n
+<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;\"><br /></p>\n
+<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:20pt;\">Contact Person</span></p>\n
+<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt;\">{contactVal}</span></p></body></html>
+<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;\"><br /></p>\n
+<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt;\">Link Acara :{linkVal}</span></p></body></html>""".format("{ white-space: pre-wrap; }",descVal=desc,contactVal=contact,linkVal=link)
+        self.textBrowser_2.setHtml(_translate("MainWindow", htmlInfo))
+
+        self.pushButton_2.setText(_translate("MainWindow", "Back"))
+        
+        if not self.isMember:
+            self.pushButton.setText(_translate("MainWindow", "Edit Acara"))
+        else:
+            conn = db.init_db()
+            cur = conn.cursor()
+
+            cur.execute("SELECT id_member FROM mengikuti WHERE id_acara = "+str(content[0]))
+            already = [i[0] for i in cur.fetchall()]
+
+            if self.idUser in already:
+                self.pushButton.setEnabled(False)
+                self.pushButton.setText(_translate("MainWindow", "Pemesanan Berhasil!"))
+            else:
+                self.pushButton.setText(_translate("MainWindow", "Pesan Tiket"))
+
+        tanggal = content[6].strftime("%d %b %Y %H:%M:%S")
+        self.label_3.setText(_translate("MainWindow", tanggal))
+
+        self.maxQ = str(content[4])
+        self.quantity = content[13] if content[13] != None else 0
+        kuota = "Kuota: " + str(self.quantity) + "/" + str(self.maxQ)
+        self.label_4.setText(_translate("MainWindow", kuota))
+
+        nama = content[1]
+        self.label.setText(_translate("MainWindow", nama))
+
+        kat1 = kategori[0]
+        self.label_6.setText(_translate("MainWindow", kat1))
+
+        kat2 = kategori[1] if len(kategori) > 1 else ""
+        self.label_7.setText(_translate("MainWindow", kat2))
+
+        kat3 = kategori[2] if len(kategori) > 2 else ""
+        self.label_8.setText(_translate("MainWindow", kat3))
+
+        kat4 = kategori[3] if len(kategori) > 3 else ""
+        self.label_9.setText(_translate("MainWindow", kat4))
+
+        organisasi = content[10]
+        self.label_10.setText(_translate("MainWindow", organisasi))
+
+        price = "Harga: Rp." + str(content[7])
+        self.label_11.setText(_translate("MainWindow", price))
+
+        self.pushButton_3.setText(_translate("MainWindow", u"Next", None))
+        self.pushButton_4.setText(_translate("MainWindow", u"Prev", None))
+    
+    def back(self):
+        self.MainWindow.close()
+
+    def nextPicture(self):
+        self.idxPhoto = self.idxPhoto +1 if self.idxPhoto +1<len(self.photos) else 0
+        img = QtGui.QImage()
+        img.loadFromData(self.photos[self.idxPhoto])
+        self.label_5.setPixmap(QtGui.QPixmap.fromImage(img))
+    
+    def prevPicture(self):
+        self.idxPhoto = self.idxPhoto -1 if self.idxPhoto -1>=0 else len(self.photos)-1
+        img = QtGui.QImage()
+        img.loadFromData(self.photos[self.idxPhoto])
+        self.label_5.setPixmap(QtGui.QPixmap.fromImage(img))
+
+    def buttonHandler(self):
+        if self.isMember:
+            first = True
+            pesan_dialog = PesanDialog(first)
+
+            while pesan_dialog.exec():
+                quantity = pesan_dialog.getQuantity()
+                conn = db.init_db()
+
+                if quantity>0 and pesan.pesanTiket(conn,self.idAcara,self.idUser,quantity):
+                    _translate = QtCore.QCoreApplication.translate
+                    self.pushButton.setEnabled(False)
+                    self.pushButton.setText(_translate("MainWindow", "Periksa Link Acara!"))
+                    kuota = "Kuota: " + str(self.quantity+quantity) + "/" + str(self.maxQ)
+                    self.label_4.setText(_translate("MainWindow", kuota))
+                    break
+                else:
+                    first = False
+                    pesan_dialog = PesanDialog(first)
+        else:
+            conn = db.init_db()
+            self.w = TambahAcaraWindow(conn=conn,
+                                       id_acara=self.idAcara,
+                                       id_penyelenggara=self.idUser)
+            self.w.show()
+
+class DetailAcaraWindow(QMainWindow, Ui_DetailAcaraWindow):
+    def __init__(self, idAcara, idMember, isMember, parent=None):
+        super().__init__(parent)
+
+        conn = db.init_db()
+        cur = conn.cursor()
+
+        # Ambil info acara
+        cur.execute('SELECT * FROM acara WHERE id_acara = {0} LIMIT 1'.format(idAcara))
+        content = cur.fetchone()
+
+        # Ambil kontak penanggungjawab
+        cur.execute("SELECT penanggung_jawab,no_wa,nama_organisasi FROM penyelenggara WHERE id_penyelenggara = "+str(content[9]))
+        val = cur.fetchone()
+        contact = val[0] + ": " + val[1]
+        contact = (contact,val[2])
+        content = tuple([content[i] for i in range(9)])
+        content += contact
+
+        # Ambil foto acara
+        cur.execute("SELECT id_foto,foto FROM foto_acara WHERE id_acara ="+str(idAcara))
+        files = cur.fetchall()
+        images = []
+        for aFile in files:
+            images.append(aFile[1])
+
+        # Ambil kategori acara
+        cur.execute("SELECT nama_kategori FROM kategori_acara WHERE id_acara = "+str(idAcara))
+        query = cur.fetchall()
+        kategori = ()
+        for val in query:
+            kategori += val
+
+        # Ambil jumlah tiket yang udah dipesan
+        cur.execute("SELECT SUM(jumlah) FROM mengikuti WHERE id_acara = "+str(idAcara))
+        jmlPesanan = cur.fetchone()
+        jmlPesanan = jmlPesanan[0]
+        content += (idMember,images,jmlPesanan)
+
+        print(content)
+        # content = (idAcara,namaAcara,linkVideo,syarat,kuota,desc,waktu,harga,link,namapenanggungjwb: noWA,namaOrganisasi,idMember,foto,jmlPesanan)
+        self.setupUi(self,content,kategori,isMember)
+
+    def about(self):
+        QMessageBox.about(
+            self,
+            "About Sample Editor",
+            "<p>A sample text editor app built with:</p>"
+            "<p>- PyQt</p>"
+            "<p>- Qt Designer</p>"
+            "<p>- Python</p>",
+        )
+
+class PesanDialog(QtWidgets.QDialog, Ui_Dialog):
+    def __init__(self,first,parent=None):
+        super().__init__(parent)
+        self.setupUi(self, first)
+
diff --git a/src/app/ui/edit_account.py b/src/app/ui/edit_account.py
index 89128ef55dd3dbd7918af14dcbe8e1644acead58..de009718a6274514e7603c0181fa7316076b3a07 100644
--- a/src/app/ui/edit_account.py
+++ b/src/app/ui/edit_account.py
@@ -21,6 +21,8 @@ class Ui_EditMember(object):
     def setupUi(self, EditMember):
         EditMember.setObjectName("EditMember")
         EditMember.resize(460, 472)
+        self.Dialog = EditMember
+
         self.buttonBox = QtWidgets.QDialogButtonBox(EditMember)
         self.buttonBox.setGeometry(QtCore.QRect(90, 420, 341, 32))
         self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
@@ -77,6 +79,7 @@ class Ui_EditMember(object):
 
         self.lineEdit_password = QtWidgets.QLineEdit(self.horizontalLayoutWidget)
         self.lineEdit_password.setObjectName("lineEdit_password")
+        self.lineEdit_password.setEchoMode(QtWidgets.QLineEdit.Password)
         self.verticalLayout_2.addWidget(self.lineEdit_password)
 
         self.textEdit_no_telp = QtWidgets.QTextEdit(self.horizontalLayoutWidget)
@@ -93,7 +96,7 @@ class Ui_EditMember(object):
         self.pic_profile = QtWidgets.QLabel(EditMember)
         self.pic_profile.setGeometry(QtCore.QRect(170, 20, 100, 100))
         self.pic_profile.setText("")
-        self.pic_profile.setPixmap(QtGui.QPixmap("Downloads/default_user.png"))
+        self.pic_profile.setPixmap(QtGui.QPixmap("assets/default_user.png"))
         self.pic_profile.setScaledContents(True)
         self.pic_profile.setObjectName("pic_profile")
 
@@ -130,6 +133,8 @@ class Ui_EditMember(object):
                 raise Exception("Invalid email")
             edit_account_member(self.conn, self.id_member, nama_dpn, nama_blkg, None, email, password, no_telp, desc)
             callInfoDialog("Successfully edited account")
+
+            self.Dialog.close()
         except Exception as err:
             callInfoDialog(str(err))
 
@@ -142,6 +147,8 @@ class Ui_EditPenyelenggara(object):
     def setupUi(self, EditPenyelenggara):
         EditPenyelenggara.setObjectName("EditPenyelenggara")
         EditPenyelenggara.resize(460, 474)
+        self.Dialog = EditPenyelenggara
+
         self.buttonBox = QtWidgets.QDialogButtonBox(EditPenyelenggara)
         self.buttonBox.setGeometry(QtCore.QRect(90, 420, 341, 32))
         self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
@@ -185,9 +192,9 @@ class Ui_EditPenyelenggara(object):
         self.textEdit_pj.setObjectName("textEdit_pj")
         self.verticalLayout_2.addWidget(self.textEdit_pj)
 
-        self.textEdit_no_telp = QtWidgets.QTextEdit(self.horizontalLayoutWidget)
-        self.textEdit_no_telp.setObjectName("textEdit_no_telp")
-        self.verticalLayout_2.addWidget(self.textEdit_no_telp)
+        self.textEdit_no_wa = QtWidgets.QTextEdit(self.horizontalLayoutWidget)
+        self.textEdit_no_wa.setObjectName("textEdit_no_wa")
+        self.verticalLayout_2.addWidget(self.textEdit_no_wa)
 
         self.textEdit_email = QtWidgets.QTextEdit(self.horizontalLayoutWidget)
         self.textEdit_email.setObjectName("textEdit_email")
@@ -195,6 +202,7 @@ class Ui_EditPenyelenggara(object):
 
         self.lineEdit_password = QtWidgets.QLineEdit(self.horizontalLayoutWidget)
         self.lineEdit_password.setObjectName("lineEdit_password")
+        self.lineEdit_password.setEchoMode(QtWidgets.QLineEdit.Password)
         self.verticalLayout_2.addWidget(self.lineEdit_password)
 
         self.textEdit_deskripsi = QtWidgets.QTextEdit(self.horizontalLayoutWidget)
@@ -207,7 +215,7 @@ class Ui_EditPenyelenggara(object):
         self.pic_profile = QtWidgets.QLabel(EditPenyelenggara)
         self.pic_profile.setGeometry(QtCore.QRect(170, 10, 100, 100))
         self.pic_profile.setText("")
-        self.pic_profile.setPixmap(QtGui.QPixmap("Downloads/default_user.png"))
+        self.pic_profile.setPixmap(QtGui.QPixmap("assets/default_user.png"))
         self.pic_profile.setScaledContents(True)
         self.pic_profile.setObjectName("pic_profile")
 
@@ -244,5 +252,6 @@ class Ui_EditPenyelenggara(object):
                 raise Exception("Invalid email")
             edit_account_penyelenggara(self.conn, self.id_penyelenggara, nama_org, pj, None, None, email, password, no_wa, desc)
             callInfoDialog("Successfully edited account")
+            self.Dialog.close()
         except Exception as err:
             callInfoDialog(str(err))
\ No newline at end of file
diff --git a/src/app/ui/file_input_dialog.py b/src/app/ui/file_input_dialog.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d0f4030cadb4195bcd0ef1e25d791ff3b7989ce
--- /dev/null
+++ b/src/app/ui/file_input_dialog.py
@@ -0,0 +1,48 @@
+from PyQt5 import QtWidgets
+
+
+class FileInput(QtWidgets.QWidget):
+    def __init__(self):
+        super().__init__()
+        self.title = 'Masukkan file-file gambar Anda'
+        self.left = 10
+        self.top = 10
+        self.width = 640
+        self.height = 480
+
+    def spawn(self, multiple: bool):
+        self.setWindowTitle(self.title)
+        self.setGeometry(self.left, self.top, self.width, self.height)
+        if multiple:
+            files = self.openFileNamesDialog()
+        else:
+            files = self.openFileNameDialog()
+
+        self.show()
+
+        return files
+
+    def openFileNameDialog(self):
+        options = QtWidgets.QFileDialog.Options()
+        options |= QtWidgets.QFileDialog.DontUseNativeDialog
+        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
+            self,
+            "QFileDialog.getOpenFileName()",
+            "",
+            "All Files (*);;Python Files (*.py)",
+            options=options)
+        if fileName:
+            print(fileName)
+
+    def openFileNamesDialog(self):
+        options = QtWidgets.QFileDialog.Options()
+        options |= QtWidgets.QFileDialog.DontUseNativeDialog
+        files, _ = QtWidgets.QFileDialog.getOpenFileNames(
+            self,
+            self.title,
+            "",
+            "Semua File (*);;File Gambar (*.png *.jpg *.jpeg)",
+            options=options)
+
+        if files:
+            return files
diff --git a/src/app/ui/linimasa_pengguna_ui.ui b/src/app/ui/linimasa_pengguna_ui.ui
new file mode 100644
index 0000000000000000000000000000000000000000..d755c4173ef59b8c5ef929edb6d479597ff72abd
--- /dev/null
+++ b/src/app/ui/linimasa_pengguna_ui.ui
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Linimasa</class>
+ <widget class="QMainWindow" name="Linimasa">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_4">
+      <property name="sizeConstraint">
+       <enum>QLayout::SetMaximumSize</enum>
+      </property>
+      <item alignment="Qt::AlignRight">
+       <widget class="QPushButton" name="edit_akun">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Ignored" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Edit Akun</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QCheckBox" name="teknologi">
+        <property name="text">
+         <string>Teknologi</string>
+        </property>
+        <property name="checked">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="motivasi">
+        <property name="text">
+         <string>Motivasi</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="ekonomi">
+        <property name="text">
+         <string>Ekonomi</string>
+        </property>
+        <property name="checked">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="kompetisi">
+        <property name="text">
+         <string>Kompetisi</string>
+        </property>
+        <property name="checked">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Search Query</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLineEdit" name="searchquery">
+        <property name="baseSize">
+         <size>
+          <width>140</width>
+          <height>0</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="searchbutton">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Search</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QScrollArea" name="scrollArea">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="widgetResizable">
+       <bool>true</bool>
+      </property>
+      <widget class="QWidget" name="linimasa_widget">
+       <property name="geometry">
+        <rect>
+         <x>0</x>
+         <y>0</y>
+         <width>776</width>
+         <height>473</height>
+        </rect>
+       </property>
+       <layout class="QVBoxLayout" name="linimasa"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <action name="actionpush1">
+   <property name="text">
+    <string>push1</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/app/ui/linimasa_penyelenggara_ui.ui b/src/app/ui/linimasa_penyelenggara_ui.ui
new file mode 100644
index 0000000000000000000000000000000000000000..2e908db6dedfe1177c5c24b45835c60fe8a1d7c9
--- /dev/null
+++ b/src/app/ui/linimasa_penyelenggara_ui.ui
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Linimasa</class>
+ <widget class="QMainWindow" name="Linimasa">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>807</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout_2">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_4">
+      <property name="sizeConstraint">
+       <enum>QLayout::SetMaximumSize</enum>
+      </property>
+      <item alignment="Qt::AlignRight">
+       <widget class="QPushButton" name="tambah_acara">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Tambah Acara</string>
+        </property>
+       </widget>
+      </item>
+      <item alignment="Qt::AlignRight">
+       <widget class="QPushButton" name="edit_akun">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Edit Akun</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QRadioButton" name="no_filter">
+        <property name="text">
+         <string>Tanpa filter</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="filter_before">
+        <property name="text">
+         <string>Belum diselenggarakan</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="filter_after">
+        <property name="text">
+         <string>Sudah diselenggarakan</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Search Query</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLineEdit" name="searchquery">
+        <property name="baseSize">
+         <size>
+          <width>140</width>
+          <height>0</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="searchbutton">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Search</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QScrollArea" name="scrollArea">
+      <property name="widgetResizable">
+       <bool>true</bool>
+      </property>
+      <widget class="QWidget" name="linimasa_widget">
+       <property name="geometry">
+        <rect>
+         <x>0</x>
+         <y>0</y>
+         <width>783</width>
+         <height>473</height>
+        </rect>
+       </property>
+       <layout class="QVBoxLayout" name="linimasa"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <action name="actionpush1">
+   <property name="text">
+    <string>push1</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/app/ui/linimasa_ui.py b/src/app/ui/linimasa_ui.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fec2735a08add36a123c71d4a23c83cc2e6b548
--- /dev/null
+++ b/src/app/ui/linimasa_ui.py
@@ -0,0 +1,131 @@
+import sys,os
+import PyQt5.QtWidgets as QtWidgets
+import PyQt5.QtCore as QtCore
+from PyQt5.QtWidgets import (
+  QMainWindow, QMessageBox, QLabel, QVBoxLayout,
+  QHBoxLayout, QWidget, QPushButton, QDialog
+)
+from PyQt5.uic import loadUi
+
+from app.modules import linimasa
+from app import main
+
+import app.ui.detail_acara_window_ui as detail
+import app.ui.edit_account as edit_account
+import app.ui.tambah_acara_ui as tambah_acara_ui
+
+class LinimasaPenggunaWindow(QMainWindow):
+  def __init__(self, id_member, windows, parent=None):
+    super().__init__(parent)
+    self.windows = windows
+    self.id_member = id_member
+    loadUi(os.path.join(os.path.dirname(__file__), 'linimasa_pengguna_ui.ui'), self)
+    self.connectSignalsSlots()
+    self.attemptSearch()
+
+  def connectSignalsSlots(self):
+    self.searchbutton.clicked.connect(self.attemptSearch)
+    self.edit_akun.clicked.connect(self.editakun)
+  
+  # ini
+  def attemptSearch(self):
+    kategs = ['motivasi', 'teknologi', 'ekonomi', 'kompetisi']
+    katfil = [x for x in kategs if getattr(self, x).isChecked()]
+    query = self.searchquery.text()
+    conn = main.init_db()
+    result = linimasa.linimasa_pengguna(conn, katfil if len(katfil) > 0 else None, query)
+    for i in reversed(range(self.linimasa.count())):
+      self.linimasa.itemAt(i).widget().deleteLater()
+    for r in result:
+      container = QWidget(self.linimasa_widget)
+      layout = QHBoxLayout(container)
+      layout.addWidget(QLabel(str(r[0])))
+      _w = QWidget(layout.widget())
+      namadetail = QVBoxLayout(_w)
+      namadetail.addWidget(QLabel(f'Nama acara: {r[1]}'))
+      namadetail.addWidget(QLabel(f'Deskripsi: {r[3]}'))
+      layout.addWidget(_w)
+      layout.addWidget(QLabel(f'Kuota Pendaftar: {r[2]}'))
+      layout.addWidget(QLabel(f'{r[4]}'))
+      button = QPushButton('Lihat acara')
+      button.clicked.connect(lambda: self.showDetails(r[0]))
+      layout.addWidget(button)
+      self.linimasa.addWidget(container)
+
+  def showDetails(self, id):
+    w = detail.DetailAcaraWindow(id, self.id_member, True)
+    self.windows.append(w)
+    w.show()
+  
+  def editakun(self):
+    conn = main.init_db()
+    Dialog = QtWidgets.QDialog()
+    w = edit_account.Ui_EditMember(conn, self.id_member)
+    w.setupUi(Dialog)
+    Dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
+    Dialog.exec_()
+
+
+class LinimasaPenyelenggaraWindow(QMainWindow):
+  def __init__(self, id_penyelenggara, windows, parent=None):
+    super().__init__(parent)
+    self.windows = windows
+    self.id_penyelenggara = id_penyelenggara
+    loadUi(os.path.join(os.path.dirname(__file__),'linimasa_penyelenggara_ui.ui'), self)
+    self.connectSignalsSlots()
+    self.attemptSearch()
+
+  def connectSignalsSlots(self):
+    self.searchbutton.clicked.connect(self.attemptSearch)
+    self.edit_akun.clicked.connect(self.editakun)
+    self.tambah_acara.clicked.connect(self.tambahacara)
+  
+  # ini
+  def attemptSearch(self):
+    ended = None
+    if self.no_filter.isChecked():
+      ended = None
+    elif self.filter_before.isChecked():
+      ended = False
+    elif self.filter_after.isChecked():
+      ended = True
+    query = self.searchquery.text()
+    conn = main.init_db()
+    result = linimasa.linimasa_penyelenggara(conn, ended, query)
+    for i in reversed(range(self.linimasa.count())):
+      self.linimasa.itemAt(i).widget().deleteLater()
+    for r in result:
+      container = QWidget(self.linimasa_widget)
+      layout = QHBoxLayout(container)
+      layout.addWidget(QLabel(str(r[0])))
+      _w = QWidget(layout.widget())
+      namadetail = QVBoxLayout(_w)
+      namadetail.addWidget(QLabel(f'Nama acara: {r[1]}'))
+      namadetail.addWidget(QLabel(f'Deskripsi: {r[3]}'))
+      layout.addWidget(_w)
+      layout.addWidget(QLabel(f'Kuota Pendaftar: {r[2]}'))
+      layout.addWidget(QLabel(f'{r[4]}'))
+      button = QPushButton('Lihat acara')
+      button.clicked.connect(lambda: self.showDetails(r[0]))
+      layout.addWidget(button)
+      self.linimasa.addWidget(container)
+
+  def editakun(self):
+    conn = main.init_db()
+    dialog = QtWidgets.QDialog()
+    ui = edit_account.Ui_EditPenyelenggara(conn, self.id_penyelenggara)
+    ui.setupUi(dialog)
+    dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
+    dialog.exec_()
+    conn.close()
+
+  def showDetails(self, id):
+    w = detail.DetailAcaraWindow(id, self.id_penyelenggara, False)
+    self.windows.append(w)
+    w.show()
+
+  def tambahacara(self):
+    conn = main.init_db()
+    w = tambah_acara_ui.TambahAcaraWindow(conn, self.id_penyelenggara)
+    self.windows.append(w)
+    w.show()
diff --git a/src/app/ui/main_window_ui.py b/src/app/ui/main_window_ui.py
index 36ac8f68b6fdb4840dc829630290a9f5f7a6e169..8b6239b76756a8df2b53e7240d2dd46f938bf280 100644
--- a/src/app/ui/main_window_ui.py
+++ b/src/app/ui/main_window_ui.py
@@ -7,16 +7,21 @@
 # WARNING! All changes made in this file will be lost!
 
 from PyQt5 import QtCore, QtGui, QtWidgets
-from .auth_ui import *
+from PyQt5.QtWidgets import QMainWindow
+from app.ui.auth_ui import *
+from app.ui.linimasa_ui import *
 
 class Ui_YesManagement(object):
-    def __init__(self, conn):
+    def __init__(self, conn, windows):
         self.conn = conn
+        self.windows = windows
 
     def setupUi(self, YesManagement):
         YesManagement.setObjectName("YesManagement")
         YesManagement.resize(800, 456)
         YesManagement.setUnifiedTitleAndToolBarOnMac(False)
+
+        self.MainWindow = YesManagement
         self.centralwidget = QtWidgets.QWidget(YesManagement)
         self.centralwidget.setObjectName("centralwidget")
 
@@ -44,6 +49,7 @@ class Ui_YesManagement(object):
         YesManagement.setStatusBar(self.statusbar)
 
         self.retranslateUi(YesManagement)
+
         QtCore.QMetaObject.connectSlotsByName(YesManagement)
 
     def retranslateUi(self, YesManagement):
@@ -67,10 +73,19 @@ class Ui_YesManagement(object):
 
     def loginButtonHandler(self):
         Dialog = QtWidgets.QDialog()
-        ui = Ui_Login_Dialog(self.conn)
+        ui = Ui_Login_Dialog(self.conn, self.MainWindow)
         ui.setupUi(Dialog)
         Dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
-        Dialog.exec_()
+        if Dialog.exec_():
+            linimasa = None
+            if ui.isPenyelenggara:
+                linimasa = LinimasaPenyelenggaraWindow(ui.id, self.windows)
+            else:
+                linimasa = LinimasaPenggunaWindow(ui.id, self.windows)
+            self.windows.append(linimasa)
+
+            linimasa.show()
+            self.MainWindow.close()
 
     def registerPenyelenggaraButtonHandler(self):
         Dialog = QtWidgets.QDialog()
diff --git a/src/app/ui/tambah_acara.ui b/src/app/ui/tambah_acara.ui
index 345f32f37d64cb88ef81982be2edc56cabe07b66..7f288942d282b9a3f51496e4b0751c1a78842f97 100644
--- a/src/app/ui/tambah_acara.ui
+++ b/src/app/ui/tambah_acara.ui
@@ -51,12 +51,12 @@
          </property>
          <layout class="QVBoxLayout" name="verticalLayout_4">
           <item>
-           <layout class="QHBoxLayout" name="ImageArea">
+           <layout class="QHBoxLayout" name="area_image">
             <property name="topMargin">
              <number>0</number>
             </property>
             <item>
-             <widget class="QToolButton" name="ImagePrev">
+             <widget class="QToolButton" name="button_image_prev">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
                 <horstretch>0</horstretch>
@@ -116,7 +116,7 @@
              </spacer>
             </item>
             <item>
-             <widget class="QLabel" name="Image">
+             <widget class="QLabel" name="image">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
                 <horstretch>0</horstretch>
@@ -172,7 +172,7 @@
              </spacer>
             </item>
             <item>
-             <widget class="QToolButton" name="ImageNext">
+             <widget class="QToolButton" name="button_image_next">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
                 <horstretch>0</horstretch>
@@ -218,7 +218,7 @@
            </layout>
           </item>
           <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_4">
+           <layout class="QHBoxLayout" name="area_add_image">
             <property name="topMargin">
              <number>0</number>
             </property>
@@ -236,7 +236,7 @@
              </spacer>
             </item>
             <item>
-             <widget class="QPushButton" name="pushButton">
+             <widget class="QPushButton" name="button_add_image">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
                 <horstretch>0</horstretch>
@@ -262,7 +262,7 @@
              </widget>
             </item>
             <item>
-             <widget class="QLabel" name="label_13">
+             <widget class="QLabel" name="catatan_image">
               <property name="font">
                <font>
                 <pointsize>10</pointsize>
@@ -318,27 +318,27 @@
                <x>0</x>
                <y>0</y>
                <width>1387</width>
-               <height>425</height>
+               <height>388</height>
               </rect>
              </property>
              <layout class="QGridLayout" name="gridLayout_2">
-              <item row="1" column="2">
-               <widget class="QLabel" name="label">
+              <item row="6" column="2">
+               <widget class="QLabel" name="label_deskripsi">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
                 <property name="text">
-                 <string>Nama Acara</string>
+                 <string>Deskripsi</string>
                 </property>
                 <property name="alignment">
                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                 </property>
                </widget>
               </item>
-              <item row="1" column="6">
-               <spacer name="horizontalSpacer_11">
+              <item row="1" column="0">
+               <spacer name="horizontalSpacer_10">
                 <property name="orientation">
                  <enum>Qt::Horizontal</enum>
                 </property>
@@ -347,14 +347,14 @@
                 </property>
                 <property name="sizeHint" stdset="0">
                  <size>
-                  <width>500</width>
+                  <width>40</width>
                   <height>20</height>
                  </size>
                 </property>
                </spacer>
               </item>
-              <item row="3" column="3">
-               <widget class="QLabel" name="label_18">
+              <item row="2" column="3">
+               <widget class="QLabel" name="wajib_waktu">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
@@ -368,67 +368,61 @@
                 </property>
                </widget>
               </item>
-              <item row="4" column="3">
-               <widget class="QLabel" name="label_19">
+              <item row="2" column="5">
+               <widget class="QDateTimeEdit" name="input_waktu">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="styleSheet">
-                 <string notr="true">color: rgb(255, 0, 0);</string>
-                </property>
-                <property name="text">
-                 <string>*</string>
+                <property name="displayFormat">
+                 <string>yyyy/MM/dd HH:mm</string>
                 </property>
                </widget>
               </item>
-              <item row="3" column="5">
-               <widget class="QSpinBox" name="spinBox_2">
+              <item row="5" column="5">
+               <widget class="QLineEdit" name="input_link">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="maximum">
-                 <number>1000000000</number>
-                </property>
                </widget>
               </item>
-              <item row="10" column="2">
-               <widget class="QLabel" name="label_15">
+              <item row="3" column="5">
+               <widget class="QSpinBox" name="input_harga">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="text">
-                 <string>Link ke Video Introduksi Acara</string>
-                </property>
-                <property name="alignment">
-                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                <property name="maximum">
+                 <number>1000000000</number>
                 </property>
                </widget>
               </item>
-              <item row="4" column="5">
-               <widget class="QSpinBox" name="spinBox">
+              <item row="3" column="3">
+               <widget class="QLabel" name="wajib_harga">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="maximum">
-                 <number>1000000000</number>
+                <property name="styleSheet">
+                 <string notr="true">color: rgb(255, 0, 0);</string>
+                </property>
+                <property name="text">
+                 <string>*</string>
                 </property>
                </widget>
               </item>
-              <item row="1" column="0">
-               <spacer name="horizontalSpacer_10">
+              <item row="1" column="4">
+               <spacer name="horizontalSpacer_12">
                 <property name="orientation">
                  <enum>Qt::Horizontal</enum>
                 </property>
                 <property name="sizeType">
-                 <enum>QSizePolicy::Expanding</enum>
+                 <enum>QSizePolicy::Fixed</enum>
                 </property>
                 <property name="sizeHint" stdset="0">
                  <size>
@@ -438,8 +432,8 @@
                 </property>
                </spacer>
               </item>
-              <item row="8" column="5">
-               <widget class="QPlainTextEdit" name="plainTextEdit_2">
+              <item row="1" column="5">
+               <widget class="QLineEdit" name="input_nama_acara">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
@@ -447,92 +441,81 @@
                 </property>
                </widget>
               </item>
-              <item row="4" column="2">
-               <widget class="QLabel" name="label_4">
-                <property name="font">
-                 <font>
-                  <pointsize>12</pointsize>
-                 </font>
-                </property>
-                <property name="text">
-                 <string>Kuota</string>
+              <item row="1" column="6">
+               <spacer name="horizontalSpacer_11">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
                 </property>
-                <property name="alignment">
-                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Expanding</enum>
                 </property>
-               </widget>
-              </item>
-              <item row="6" column="5">
-               <widget class="QPlainTextEdit" name="plainTextEdit">
-                <property name="font">
-                 <font>
-                  <pointsize>12</pointsize>
-                 </font>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>500</width>
+                  <height>20</height>
+                 </size>
                 </property>
-               </widget>
+               </spacer>
               </item>
-              <item row="2" column="3">
-               <widget class="QLabel" name="label_17">
+              <item row="5" column="2">
+               <widget class="QLabel" name="label_link">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="styleSheet">
-                 <string notr="true">color: rgb(255, 0, 0);</string>
-                </property>
                 <property name="text">
-                 <string>*</string>
+                 <string>Link ke Conference</string>
+                </property>
+                <property name="alignment">
+                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                 </property>
                </widget>
               </item>
-              <item row="8" column="2">
-               <widget class="QLabel" name="label_6">
+              <item row="4" column="2">
+               <widget class="QLabel" name="label_kuota">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
                 <property name="text">
-                 <string>Syarat</string>
+                 <string>Kuota</string>
                 </property>
                 <property name="alignment">
                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                 </property>
                </widget>
               </item>
-              <item row="6" column="2">
-               <widget class="QLabel" name="label_5">
+              <item row="3" column="2">
+               <widget class="QLabel" name="label_harga">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
                 <property name="text">
-                 <string>Deskripsi</string>
+                 <string>Harga</string>
                 </property>
                 <property name="alignment">
                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                 </property>
                </widget>
               </item>
-              <item row="1" column="3">
-               <widget class="QLabel" name="label_16">
+              <item row="4" column="5">
+               <widget class="QSpinBox" name="input_kuota">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="styleSheet">
-                 <string notr="true">color: rgb(255, 0, 0);</string>
-                </property>
-                <property name="text">
-                 <string>*</string>
+                <property name="maximum">
+                 <number>1000000000</number>
                 </property>
                </widget>
               </item>
               <item row="2" column="2">
-               <widget class="QLabel" name="label_2">
+               <widget class="QLabel" name="label_waktu">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
@@ -546,89 +529,67 @@
                 </property>
                </widget>
               </item>
-              <item row="10" column="5">
-               <widget class="QLineEdit" name="lineEdit_3">
+              <item row="8" column="2">
+               <widget class="QLabel" name="label_syarat">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-               </widget>
-              </item>
-              <item row="1" column="4">
-               <spacer name="horizontalSpacer_12">
-                <property name="orientation">
-                 <enum>Qt::Horizontal</enum>
-                </property>
-                <property name="sizeType">
-                 <enum>QSizePolicy::Fixed</enum>
-                </property>
-                <property name="sizeHint" stdset="0">
-                 <size>
-                  <width>40</width>
-                  <height>20</height>
-                 </size>
+                <property name="text">
+                 <string>Syarat</string>
                 </property>
-               </spacer>
-              </item>
-              <item row="1" column="5">
-               <widget class="QLineEdit" name="lineEdit">
-                <property name="font">
-                 <font>
-                  <pointsize>12</pointsize>
-                 </font>
+                <property name="alignment">
+                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                 </property>
                </widget>
               </item>
-              <item row="2" column="5">
-               <widget class="QDateTimeEdit" name="dateTimeEdit">
+              <item row="1" column="2">
+               <widget class="QLabel" name="label_nama_acara">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="displayFormat">
-                 <string>yyyy/MM/dd HH:mm</string>
+                <property name="text">
+                 <string>Nama Acara</string>
+                </property>
+                <property name="alignment">
+                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                 </property>
                </widget>
               </item>
-              <item row="3" column="2">
-               <widget class="QLabel" name="label_3">
+              <item row="8" column="5">
+               <widget class="QPlainTextEdit" name="input_syarat">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="text">
-                 <string>Harga</string>
-                </property>
-                <property name="alignment">
-                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-                </property>
                </widget>
               </item>
-              <item row="5" column="2">
-               <widget class="QLabel" name="label_14">
+              <item row="6" column="5">
+               <widget class="QPlainTextEdit" name="input_deskripsi">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
-                <property name="text">
-                 <string>Link ke Conference</string>
-                </property>
-                <property name="alignment">
-                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-                </property>
                </widget>
               </item>
-              <item row="5" column="5">
-               <widget class="QLineEdit" name="lineEdit_2">
+              <item row="1" column="3">
+               <widget class="QLabel" name="wajib_nama">
                 <property name="font">
                  <font>
                   <pointsize>12</pointsize>
                  </font>
                 </property>
+                <property name="styleSheet">
+                 <string notr="true">color: rgb(255, 0, 0);</string>
+                </property>
+                <property name="text">
+                 <string>*</string>
+                </property>
                </widget>
               </item>
              </layout>
@@ -636,7 +597,7 @@
            </widget>
           </item>
           <item>
-           <layout class="QGridLayout" name="KategoriArea">
+           <layout class="QGridLayout" name="area_kategori">
             <property name="leftMargin">
              <number>50</number>
             </property>
@@ -669,7 +630,7 @@
              </spacer>
             </item>
             <item row="2" column="1">
-             <widget class="QCheckBox" name="Kompetisi">
+             <widget class="QCheckBox" name="kompetisi">
               <property name="font">
                <font>
                 <pointsize>11</pointsize>
@@ -694,7 +655,7 @@
              </spacer>
             </item>
             <item row="1" column="2">
-             <widget class="QCheckBox" name="Motivasi">
+             <widget class="QCheckBox" name="motivasi">
               <property name="font">
                <font>
                 <pointsize>11</pointsize>
@@ -706,7 +667,7 @@
              </widget>
             </item>
             <item row="2" column="2">
-             <widget class="QCheckBox" name="Ekonomi">
+             <widget class="QCheckBox" name="ekonomi">
               <property name="font">
                <font>
                 <pointsize>11</pointsize>
@@ -718,7 +679,7 @@
              </widget>
             </item>
             <item row="1" column="1">
-             <widget class="QCheckBox" name="Teknologi">
+             <widget class="QCheckBox" name="teknologi">
               <property name="font">
                <font>
                 <pointsize>11</pointsize>
@@ -756,7 +717,7 @@
              </spacer>
             </item>
             <item row="0" column="1" colspan="2">
-             <widget class="QLabel" name="KategoriAreaText">
+             <widget class="QLabel" name="kategori_area_text">
               <property name="font">
                <font>
                 <pointsize>14</pointsize>
@@ -781,7 +742,7 @@
            </layout>
           </item>
           <item>
-           <layout class="QHBoxLayout" name="ButtonArea">
+           <layout class="QHBoxLayout" name="area_button">
             <property name="topMargin">
              <number>25</number>
             </property>
@@ -802,7 +763,7 @@
              </spacer>
             </item>
             <item>
-             <widget class="QPushButton" name="Simpan">
+             <widget class="QPushButton" name="button_simpan">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
                 <horstretch>0</horstretch>
@@ -848,7 +809,7 @@
              </spacer>
             </item>
             <item>
-             <widget class="QPushButton" name="Batal">
+             <widget class="QPushButton" name="button_batal">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
                 <horstretch>0</horstretch>
diff --git a/src/app/ui/tambah_acara_ui.py b/src/app/ui/tambah_acara_ui.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1c465fb68f21379278e58171cbe2526d6db3660
--- /dev/null
+++ b/src/app/ui/tambah_acara_ui.py
@@ -0,0 +1,238 @@
+from PyQt5 import uic, QtWidgets, QtGui, QtCore
+import sys, os
+from app.modules.tambah_acara import tambah_acara
+from app.db import init_db
+from file_input_dialog import FileInput
+
+
+class TambahAcaraWindow(QtWidgets.QMainWindow):
+    def __init__(self, conn, id_penyelenggara, id_acara=None):
+        '''
+        Asumsi `data` valid, memiliki key:
+            - id_penyelenggara: int
+            - nama_acara: str
+            - kuota_pendaftar: int
+            - waktu: datetime (year, month, date, hour, minute)
+            - harga: int
+            - kategori: list[str], nilai yang boleh: Teknologi, Motivasi,
+                        Ekonomi, Kompetisi
+            - foto: list[bytes] isi file foto
+            - link: str
+            - syarat: str
+            - video_introduksi: str
+            - id_acara: str
+        '''
+        super(TambahAcaraWindow, self).__init__()
+        uic.loadUi(os.path.join(os.path.dirname(__file__), 'tambah_acara.ui'), self)
+
+        default_img_content = b''
+        with open(os.path.join(os.path.dirname(__file__), 'assets/no-image-available.jpeg'), 'rb') as f:
+            default_img_content = f.read()
+
+        self.__conn = conn
+        self.__id_penyelenggara = id_penyelenggara # ga boleh None
+        self.__id_acara = id_acara
+        data_acara = dict(
+            id_penyelenggara=self.__id_penyelenggara,
+            nama_acara=None,
+            kuota_pendaftar=None,
+            waktu=None,
+            harga=None,
+            kategori=list(),
+            foto=list(),
+            link=None,
+            deskripsi=None,
+            syarat=None,
+            id_acara=None,
+        )
+        if id_acara is not None:
+            cur = conn.cursor()
+            self.__get_data_from_db(data_acara=data_acara, cur=cur)
+
+        self.__current_image_counter = 0
+        self.__photos =\
+            list() if data_acara['foto'] is None else data_acara['foto']
+        # self.__penyelenggara = data_acara['id_penyelenggara'] # ga boleh None
+        self.__penyelenggara = 1
+        self.__id_acara = data_acara['id_acara']
+
+        # setting default image
+        self.__default_img = QtGui.QImage()
+        assert self.__default_img.loadFromData(default_img_content)
+
+        self.__fill_data(data_acara)
+        self.__init_button()
+
+        self.show()
+
+    def __get_data_from_db(self, data_acara, cur):
+        cur.execute('SELECT * FROM acara WHERE id_acara = ?', (self.__id_acara,))
+
+        for (_, nama_acara,
+            _, syarat_pendaftaran,
+            kuota_pendaftar, deskripsi,
+            waktu, harga,
+            link, _) in cur:
+            data_acara['nama_acara'] = nama_acara
+            data_acara['kuota_pendaftar'] = kuota_pendaftar
+            data_acara['waktu'] = waktu
+            data_acara['harga'] = harga
+            data_acara['deskripsi'] = deskripsi
+            data_acara['syarat'] = syarat_pendaftaran
+            data_acara['link'] = link
+
+        cur.execute('SELECT foto FROM foto_acara WHERE id_acara = ?',
+            (self.__id_acara,))
+        for foto in cur:
+            data_acara['foto'].append(foto[0])
+
+        cur.execute(
+            'SELECT nama_kategori FROM kategori_acara WHERE id_acara = ?',
+            (self.__id_acara,))
+        for kategori in cur:
+            data_acara['kategori'].append(kategori[0])
+
+    def __set_image(self):
+        if len(self.__photos) == 0:
+            self.image.setPixmap(QtGui.QPixmap.fromImage(self.__default_img))
+        else:
+            self.image.setPixmap(
+                QtGui.QPixmap.fromImage(
+                    self.__photos[self.__current_image_counter]))
+
+    def __next_image(self):
+        try:
+            self.__current_image_counter += 1
+            self.__current_image_counter %= len(self.__photos)
+            self.__set_image()
+        except Exception:
+            pass
+
+    def __prev_image(self):
+        try:
+            self.__current_image_counter -= 1
+            self.__current_image_counter %= len(self.__photos)
+            self.__set_image()
+        except Exception:
+            pass
+
+    def __fill_data(self, data_acara):
+        '''
+        Fungsi untuk mengisi form data, foto, serta kategori acara
+        '''
+        # Ngeset foto
+        self.__set_image()
+
+        # Ngeset isi form
+        if data_acara['nama_acara'] is not None:
+            self.input_nama_acara.setText(data_acara['nama_acara'])
+
+        if data_acara['kuota_pendaftar'] is not None:
+            self.input_kuota.setValue(data_acara['kuota_pendaftar'])
+
+        self.input_waktu.setMinimumDateTime(QtCore.QDateTime.currentDateTime())
+        if data_acara['waktu'] is not None:
+            # ex:
+            # self.input_waktu.setDateTime(
+            #   datetime.strptime('2100-05-12 23:59', '%Y-%m-%d %H:%M'))
+            # asumsi udah pasti date time
+            self.input_waktu.setDateTime(data_acara['waktu'])
+        else:
+            self.input_waktu.setDateTime(QtCore.QDateTime.currentDateTime())
+
+        if data_acara['harga'] is not None:
+            self.input_harga.setValue(data_acara['harga'])
+
+        if data_acara['link'] is not None:
+            self.input_link.setText(data_acara['link'])
+
+        if data_acara['deskripsi'] is not None:
+            self.input_deskripsi.insertPlainText(data_acara['deskripsi'])
+
+        if data_acara['syarat'] is not None:
+            self.input_syarat.insertPlainText(data_acara['syarat'])
+
+        # Ngeset kategori
+        if data_acara['kategori'] is not None:
+            # Teknologi, Motivasi, Kompetisi, Ekonomi
+            for kategori in data_acara['kategori']:
+                if kategori == 'Teknologi':
+                    self.teknologi.setChecked(True)
+                elif kategori == 'Motivasi':
+                    self.motivasi.setChecked(True)
+                elif kategori == 'Kompetisi':
+                    self.kompetisi.setChecked(True)
+                elif kategori == 'Ekonomi':
+                    self.ekonommi.setChecked(True)
+
+    def __init_button(self):
+        '''
+        Fungsi untuk menyiapkan tombol-tombol
+        '''
+        self.button_image_next.clicked.connect(self.__next_image)
+        self.button_image_prev.clicked.connect(self.__prev_image)
+        self.button_batal.clicked.connect(self.close)
+        self.button_simpan.clicked.connect(self.__save_data)
+        self.button_add_image.clicked.connect(self.__input_image)
+
+    def __get_checked_kategori(self):
+        kategs = ['motivasi', 'teknologi', 'ekonomi', 'kompetisi']
+        return [x for x in kategs if getattr(self, x).isChecked()]
+
+    def __get_form_data(self):
+        return dict(
+            id_penyelenggara=self.__id_penyelenggara,
+            id_acara=self.__id_acara,
+            foto=self.__photos,
+            kategori=self.__get_checked_kategori(),
+            nama_acara=self.input_nama_acara.text(),
+            kuota_pendaftar=self.input_kuota.value(),
+            waktu=self.input_waktu.dateTime().toPyDateTime().replace(
+                microsecond=0),
+            harga=self.input_harga.value(),
+            link=self.input_link.text(),
+            deskripsi=self.input_deskripsi.toPlainText(),
+            syarat=self.input_syarat.toPlainText(),
+        )
+
+    def __save_data(self):
+        if self.__is_form_valid():
+            if tambah_acara(**self.__get_form_data(), conn=self.__conn):
+                self.close()  # sekarang exit aja dlu
+            else:
+                self.__alert(text="Gagal menambahkan data.",
+                             info="Silakan hubungi pembuat aplikasi.",
+                             title="Terjadi kegagalan")
+        else:
+            self.__alert(text="Ada data yang belum diisi.",
+                         info="Perhatikan, data dengan * merah adalah wajib\
+                               dan minimal sebuah kategori terpilih.",
+                         title="Data acara kurang")
+
+    def __input_image(self):
+        dg = FileInput()
+        files = dg.spawn(multiple=True)
+        for file in files:
+            content = b''
+            with open(file, 'rb') as f:
+                content = f.read()
+            img = QtGui.QImage()
+            assert img.loadFromData(content)
+            self.__photos.append(img)
+        self.__set_image()
+
+    def __is_form_valid(self):
+        return self.input_nama_acara is not None\
+               and self.input_nama_acara.text() != ""\
+               and self.input_waktu is not None\
+               and self.input_harga is not None\
+               and len(self.__get_checked_kategori()) != 0
+
+    def __alert(self, text, info, title):
+        msg = QtWidgets.QMessageBox()
+        msg.setIcon(QtWidgets.QMessageBox.Warning)
+        msg.setText(text)
+        msg.setInformativeText(info)
+        msg.setWindowTitle(title)
+        msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
+        msg.exec_()
diff --git a/src/test/linimasa_test.py b/src/test/linimasa_test.py
index 6ee831c290fa41d6381d8b09022fea61f58b2d71..40c2fd4ba138f11e72204d9155b3f4646b188dbc 100644
--- a/src/test/linimasa_test.py
+++ b/src/test/linimasa_test.py
@@ -3,7 +3,7 @@ from mariadb._mariadb import connection
 from datetime import datetime
 from app.modules.linimasa import *
 
-def test_linimasaPengguna_satuHasil():
+def test_linimasa_pengguna_satuHasil():
   conn = MagicMock(spec=connection)
   now = datetime.now()
 
@@ -15,7 +15,7 @@ def test_linimasaPengguna_satuHasil():
 
   conn.cursor = MagicMock(return_value=cur)
 
-  res = linimasaPengguna(conn)
+  res = linimasa_pengguna(conn)
   assert len(res) == 1
   res = res[0]
   assert res[0] == 1
@@ -27,7 +27,7 @@ def test_linimasaPengguna_satuHasil():
   assert res[5][0] == 'teknologi'
   pass
 
-def test_linimasaPengguna_banyakHasil():
+def test_linimasa_pengguna_banyakHasil():
   conn = MagicMock(spec=connection)
   now = datetime.now()
 
@@ -47,7 +47,7 @@ def test_linimasaPengguna_banyakHasil():
 
   conn.cursor = MagicMock(return_value=cur)
 
-  res = linimasaPengguna(conn)
+  res = linimasa_pengguna(conn)
   assert len(res) == 2
   assert len(res[0][5]) == 1
   assert len(res[1][5]) == 1
@@ -55,7 +55,7 @@ def test_linimasaPengguna_banyakHasil():
   assert res[1][0] == 2
   pass
 
-def test_linimasaPenyelenggara_satuHasil():
+def test_linimasa_penyelenggara_satuHasil():
   conn = MagicMock(spec=connection)
   now = datetime.now()
 
@@ -67,7 +67,7 @@ def test_linimasaPenyelenggara_satuHasil():
 
   conn.cursor = MagicMock(return_value=cur)
 
-  res = linimasaPenyelenggara(conn)
+  res = linimasa_penyelenggara(conn)
   assert len(res) == 1
   res = res[0]
   assert res[0] == 1
@@ -80,7 +80,7 @@ def test_linimasaPenyelenggara_satuHasil():
   pass
 
 
-def test_linimasaPenyelenggara_banyakHasil():
+def test_linimasa_penyelenggara_banyakHasil():
   conn = MagicMock(spec=connection)
   now = datetime.now()
 
@@ -100,7 +100,7 @@ def test_linimasaPenyelenggara_banyakHasil():
 
   conn.cursor = MagicMock(return_value=cur)
 
-  res = linimasaPenyelenggara(conn)
+  res = linimasa_penyelenggara(conn)
   assert len(res) == 2
   assert len(res[0][5]) == 1
   assert len(res[1][5]) == 1
diff --git a/src/test/tambahAcara_test.py b/src/test/tambahAcara_test.py
deleted file mode 100644
index 43c9d81bbf6e935c865213926dbb308a0cf8310f..0000000000000000000000000000000000000000
--- a/src/test/tambahAcara_test.py
+++ /dev/null
@@ -1,117 +0,0 @@
-'''
-Modul untuk menguji tambah_acara
-'''
-from app.modules.tambahAcara import tambah_acara
-from datetime import datetime
-from app.db import init_db as init_connection
-
-
-def test_add_acara():
-    now = datetime.now()
-    conn = init_connection()
-    cur = conn.cursor()
-
-    nama_acara = 'a'
-    kuota = 100
-
-    assert tambah_acara(
-        id_penyelenggara=1,
-        nama_acara=nama_acara,
-        kuota_pendaftar=100,
-        harga=0,
-        link='a',
-        waktu=now,
-        conn=conn
-    )
-
-    cur.execute(
-        'SELECT nama_acara, kuota_pendaftar FROM acara WHERE nama_acara = ?', (nama_acara,))
-
-    res = []
-    for nama, kuota in cur:
-        res.append((nama, kuota))
-
-    assert len(res) == 1
-    assert res[0][0] == nama_acara
-    assert res[0][1] == kuota
-
-    cur.execute('DELETE FROM acara WHERE nama_acara = ?', (nama_acara,))
-    conn.commit()
-
-
-def test_add_acara_fail():
-    conn = init_connection()
-    assert tambah_acara(
-        id_penyelenggara=1,
-        nama_acara='a',
-        kuota_pendaftar='X',
-        waktu=datetime.now(),
-        harga='Y',
-        conn=conn
-    ) == False
-
-
-def test_add_acara_fail_date_bad_string():
-    conn = init_connection()
-    assert tambah_acara(
-        id_penyelenggara=1,
-        nama_acara='a',
-        kuota_pendaftar=100,
-        waktu='BAD STRING',
-        harga=0,
-        conn=conn
-    ) == False
-
-
-def test_update_acara():
-    now = datetime.now()
-    conn = init_connection()
-    cur = conn.cursor()
-
-    nama_acara = 'a'
-    kuota = 100
-
-    # insert dlu
-    assert tambah_acara(
-        id_penyelenggara=1,
-        nama_acara=nama_acara,
-        kuota_pendaftar=100,
-        harga=0,
-        link='a',
-        waktu=now,
-        conn=conn
-    )
-
-    cur.execute('SELECT id_acara FROM acara WHERE nama_acara = ?', (nama_acara,))
-
-    id = 0
-    for id_res in cur:
-        id = id_res[0]
-
-    print(id)
-
-    assert tambah_acara(
-        id_penyelenggara=1,
-        id_acara=id,
-        nama_acara=str(nama_acara + 'hadeh'),
-        kuota_pendaftar=100,
-        harga=0,
-        link='a',
-        waktu=now,
-        conn=conn
-    )
-
-    cur.execute('SELECT nama_acara, kuota_pendaftar FROM acara WHERE nama_acara = ?', (str(
-        nama_acara + 'hadeh'),))
-
-    res = []
-    for nama, kuota in cur:
-        res.append((nama, kuota))
-
-    assert len(res) == 1
-    assert res[0][0] == str(nama_acara + 'hadeh')
-    assert res[0][1] == kuota
-
-    cur.execute('DELETE FROM acara WHERE nama_acara = ?',
-                (str(nama_acara + 'hadeh'),))
-    conn.commit()
diff --git a/src/test/tambah_acara_test.py b/src/test/tambah_acara_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..582d01b0523130c27d8af5a74a776f31bff26e13
--- /dev/null
+++ b/src/test/tambah_acara_test.py
@@ -0,0 +1,266 @@
+'''
+Modul untuk menguji tambah_acara
+'''
+from app.modules.tambah_acara import tambah_acara, remove_category, remove_foto
+from app.db import init_db as init_connection
+from datetime import datetime
+
+
+def test_add_acara():
+    now = datetime.now().replace(microsecond=0)
+    conn = init_connection()
+    cur = conn.cursor()
+
+    nama_acara = 'a'
+    kuota = 100
+
+    assert tambah_acara(
+        id_penyelenggara=1,
+        nama_acara=nama_acara,
+        kuota_pendaftar=100,
+        harga=0,
+        link='a',
+        kategori=['Teknologi'],
+        foto=[b'111'],
+        waktu=now,
+        conn=conn
+    )
+
+    cur.execute(
+        '''SELECT nama_acara, kuota_pendaftar, nama_kategori, foto
+            FROM acara JOIN
+                kategori_acara USING(id_acara) JOIN
+                foto_acara USING(id_acara)
+            WHERE nama_acara = ?''', (nama_acara,))
+
+    res = []
+    for nama, kuota, kateg, foto in cur:
+        res.append((nama, kuota, kateg, foto))
+
+    assert len(res) == 1
+    assert res[0][0] == nama_acara
+    assert res[0][1] == kuota
+    assert res[0][2] == 'Teknologi'
+    assert res[0][3] == b'111'
+
+    cur.execute('DELETE FROM acara WHERE nama_acara = ?', (nama_acara,))
+    conn.commit()
+
+
+def test_add_acara_fail_bad_integer():
+    conn = init_connection()
+    assert not tambah_acara(
+        id_penyelenggara=1,
+        nama_acara='a',
+        kuota_pendaftar='X',
+        waktu=datetime.now(),
+        harga='Y',
+        kategori=['Teknologi'],
+        conn=conn
+    )
+
+
+def test_add_acara_fail_date_bad_string():
+    conn = init_connection()
+    assert not tambah_acara(
+        id_penyelenggara=1,
+        nama_acara='a',
+        kuota_pendaftar=100,
+        waktu='BAD STRING',
+        harga=0,
+        kategori=['Teknologi'],
+        conn=conn
+    )
+
+
+def test_add_acara_fail_wrong_kategori():
+    conn = init_connection()
+    assert not tambah_acara(
+        id_penyelenggara=1,
+        nama_acara='a',
+        kuota_pendaftar=100,
+        waktu='BAD STRING',
+        harga=0,
+        kategori=['Mukbang'],
+        conn=conn
+    )
+
+
+def test_add_acara_fail_empty_kategori():
+    conn = init_connection()
+    assert not tambah_acara(
+        id_penyelenggara=1,
+        nama_acara='a',
+        kuota_pendaftar=100,
+        waktu=datetime.now(),
+        harga=0,
+        kategori=[],
+        conn=conn
+    )
+
+
+def test_update_acara():
+    now = datetime.now().replace(microsecond=0)
+    conn = init_connection()
+    cur = conn.cursor()
+
+    nama_acara = 'a'
+    kuota = 100
+
+    # insert dlu
+    assert tambah_acara(
+        id_penyelenggara=1,
+        nama_acara=nama_acara,
+        kuota_pendaftar=100,
+        harga=0,
+        link='a',
+        waktu=now,
+        kategori=['Teknologi'],
+        foto=[b'111'],
+        conn=conn
+    )
+
+    cur.execute(
+            'SELECT id_acara FROM acara WHERE nama_acara = ?',
+            (nama_acara,))
+
+    id = 0
+    for id_res in cur:
+        id = id_res[0]
+
+    assert tambah_acara(
+        id_penyelenggara=1,
+        id_acara=id,
+        nama_acara=str(nama_acara + 'hadeh'),
+        kuota_pendaftar=100,
+        harga=0,
+        link='a',
+        waktu=now,
+        kategori=['Teknologi', 'Motivasi'],
+        foto=[b'111', b'222'],
+        conn=conn
+    )
+
+    cur.execute(
+        'SELECT nama_acara, kuota_pendaftar FROM acara WHERE id_acara = ?',
+        (id,))
+
+    res = []
+    for nama, kuota in cur:
+        res.append((nama, kuota))
+
+    assert len(res) == 1
+    assert res[0][0] == str(nama_acara + 'hadeh')
+    assert res[0][1] == kuota
+
+    res = []
+    cur.execute(
+        'SELECT nama_kategori FROM kategori_acara WHERE id_acara = ?', (id,))
+    for nama_kategori in cur:
+        res.append(nama_kategori[0])
+
+    assert len(res) == 2
+    assert res[0] == 'Motivasi'
+    assert res[1] == 'Teknologi'
+
+    res = []
+    cur.execute(
+        'SELECT foto FROM foto_acara WHERE id_acara = ?', (id,))
+    for foto in cur:
+        res.append(foto[0])
+
+    assert len(res) == 2
+    assert res[0] == b'111'
+    assert res[1] == b'222'
+
+    cur.execute(
+            'DELETE FROM acara WHERE nama_acara = ?',
+            (str(nama_acara + 'hadeh'),))
+    conn.commit()
+
+
+def test_remove_foto():
+    nama_acara = 'a'
+    now = datetime.now().replace(microsecond=0)
+    conn = init_connection()
+
+    assert tambah_acara(
+        id_penyelenggara=1,
+        nama_acara=nama_acara,
+        kuota_pendaftar=100,
+        harga=0,
+        link='a',
+        waktu=now,
+        kategori=['Teknologi', 'Motivasi'],
+        foto=[b'111', b'222'],
+        conn=conn
+    )
+
+    cur = conn.cursor()
+    cur.execute(
+            'SELECT id_acara FROM acara WHERE nama_acara = ?', (nama_acara,))
+
+    id = 0
+    for id_res in cur:
+        id = id_res[0]
+
+    cur.execute(
+            'SELECT id_foto FROM foto_acara WHERE id_acara = ? AND foto = ?',
+            (id, b'111'))
+    id_foto = 0
+    for id_res in cur:
+        id_foto = id_res[0]
+
+    assert remove_foto(id_foto=id_foto, id_acara=id, conn=conn)
+
+    cur.execute(
+            'SELECT id_foto FROM foto_acara WHERE id_acara = ? AND foto = ?',
+            (id, b'111'))
+    i = 0
+    for _ in cur:
+        i += 1
+    assert i == 0
+
+    cur.execute('DELETE FROM acara WHERE nama_acara = ?', (nama_acara,))
+    conn.commit()
+
+
+def test_remove_categ():
+    nama_acara = 'a'
+    now = datetime.now().replace(microsecond=0)
+    conn = init_connection()
+
+    assert tambah_acara(
+        id_penyelenggara=1,
+        nama_acara=nama_acara,
+        kuota_pendaftar=100,
+        harga=0,
+        link='a',
+        waktu=now,
+        kategori=['Teknologi', 'Motivasi'],
+        foto=[b'111', b'222'],
+        conn=conn
+    )
+
+    cur = conn.cursor()
+    cur.execute(
+            'SELECT id_acara FROM acara WHERE nama_acara = ?',
+            (nama_acara,))
+
+    id = 0
+    for id_res in cur:
+        id = id_res[0]
+
+    assert remove_category(id_acara=id, kateg='Teknologi', conn=conn)
+    cur.execute(
+            '''SELECT id_acara
+                FROM kategori_acara
+                WHERE id_acara = ? AND nama_kategori = ?''',
+            (id, 'Teknologi'))
+    i = 0
+    for _ in cur:
+        i += 1
+    assert i == 0
+
+    cur.execute('DELETE FROM acara WHERE nama_acara = ?', (nama_acara,))
+    conn.commit()