diff --git a/administration/templates/administration/includes/sidebar.html b/administration/templates/administration/includes/sidebar.html
index 76be2e9d24d0e05fd64af810c4cacdeefa3ef04f..6f639a5e1be5c11e6aa51de3c22edc30491d636f 100644
--- a/administration/templates/administration/includes/sidebar.html
+++ b/administration/templates/administration/includes/sidebar.html
@@ -50,6 +50,11 @@
     <!-- Divider -->
     <hr class="sidebar-divider my-0">
 
+    <li class="nav-item">
+      <a class="nav-link" href="/administration/kelola-materi">
+        <span>Kelola Materi</span></a>
+    </li>
+
     <li class="nav-item">
       <a class="nav-link" href="/administration/news/list">
         <span>Kelola Berita</span></a>
diff --git a/administration/templates/kelola_materi.html b/administration/templates/kelola_materi.html
new file mode 100644
index 0000000000000000000000000000000000000000..0e4a293d5aff71d0f7e42e97f8ff9225100cafed
--- /dev/null
+++ b/administration/templates/kelola_materi.html
@@ -0,0 +1,67 @@
+{% extends 'administration/base_administrasi2.html' %}
+{% load static %}
+
+{% block title %}
+<title>Kelola Admin | Digipus</title>
+{% endblock %}
+
+{% block content %}
+<!-- Page Heading -->
+<h1 class="h3 mb-2 text-gray-800">Kelola Admin</h1>
+<p class="mb-4">Tekan tombol detail untuk informasi lebih lanjut tentang admin</ehp>
+
+<!-- DataTales Example -->
+<div class="card shadow mb-4">
+  <div class="card-header py-3">
+    <div class="d-flex">
+      <div class="mr-auto p-2">
+        <h6 id="table-description" class="m-0 font-weight-bold text-primary">Tabel Daftar Approved Material</h6>
+      </div>
+    </div>
+  </div>
+  <div class="card-body">
+    <div class="table-responsive">
+      <table aria-describedby="table-description" class="table table-bordered" id="dataTable">
+        <thead>
+          <tr>
+            <th scope="col">Title</th>
+            <th scope="col">Cover</th>
+            <th scope="col">Content</th>
+            <th scope="col">Kontributor</th>
+            <th scope="col">Status</th>
+            <th scope="col">Jumlah Like</th>
+          </tr>
+        </thead>
+        <tfoot>
+          <tr>
+            <th scope="col">Title</th>
+            <th scope="col">Cover</th>
+            <th scope="col">Content</th>
+            <th scope="col">Kontributor</th>
+            <th scope="col">Status</th>
+            <th scope="col">Jumlah Like</th>
+          </tr>
+          </tr>
+        </tfoot>
+        <tbody>
+          {% for materi in materi_list %}
+          <tr>
+            <td>{{ materi.title }}</td>
+            <td>
+              {% if materi.cover %}
+              <img id="posts-img" src="{{ materi.cover.url }}" alt="cover-picture" style="max-width: 400px;"/>
+              {% endif %}
+            </td>
+            <td>
+              <a href="/materi/{{materi.id}}/view">Lihat konten</a></td>
+            <td>{{ materi.uploader }}</td>
+            <td>{{ materi.status }}</td>
+            <td>{{ materi.like_count }}</td>
+          </tr>
+          {% endfor %}
+        </tbody>
+      </table>
+    </div>
+  </div>
+</div>
+{% endblock %}
diff --git a/administration/tests.py b/administration/tests.py
index 5276b460e8f6b99e66cc46326dcbece0122823c0..fff6daef00396bad3176cbc8c260e3d7f6fd27b4 100644
--- a/administration/tests.py
+++ b/administration/tests.py
@@ -10,6 +10,8 @@ from app.models import Category, Materi
 from authentication.models import User
 from bs4 import BeautifulSoup
 
+from datetime import datetime
+
 EDIT_ENDPOINT = "/edit"
 ERROR_403_MESSAGE = 'Kamu harus login untuk mengakses halaman ini'
 
@@ -1175,3 +1177,115 @@ class EditAdminStatusTests(TestCase):
         response = self.client.get(self.edit_url_dummy_superuser)
 
         self.assertEqual(response.status_code, 403)
+
+
+class KelolaMateriViewTests(TestCase):
+    def setUp(self):
+        self.client = Client()
+        self.url = "/administration/kelola-materi/"
+        self.template_name = "kelola_materi.html"
+        self.view = views.KelolaMateriView
+
+        self.user_credential = {
+            "email": "user@gov.id",
+            "password": id_generator()
+        }
+        self.admin_credential = {
+            "email": "admin@gov.id",
+            "password": id_generator()
+        }
+
+        self.user = get_user_model().objects.create_user(
+            **self.user_credential, name="User", is_admin=False)    
+        self.admin = get_user_model().objects.create_user(
+            **self.admin_credential, name="Admin", is_admin=True)
+        
+        self.contributor = User.objects.create( 
+            email="kontributor@gov.id",
+            password="passwordtest",
+            name="kontributor",
+            is_contributor=True
+        )
+
+        self.cover = SimpleUploadedFile(
+            "Cherprang_Areekul40_nJM9dGt.jpg", b"Test file")
+        self.content = SimpleUploadedFile("Bahan_PA_RKK.pdf", b"Test file")
+
+    def test_kelola_materi_view(self):
+        found = resolve(self.url)
+        self.assertEqual(found.func.__name__, self.view.as_view().__name__)
+
+    def test_kelola_materi_template(self):
+        self.client.login(**self.admin_credential)
+        response = self.client.get(self.url)
+        self.assertTemplateUsed(response, self.template_name)
+
+    def test_cannot_access_kelola_materi_as_unauthenticated_user(self):
+        response = self.client.get(self.url)
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_cannot_access_kelola_materi_as_user_non_admin(self):
+        self.client.login(**self.user_credential)
+        response = self.client.get(self.url)
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_can_access_kelola_materi_as_admin(self):
+        self.client.login(**self.admin_credential)
+        response = self.client.get(self.url)
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_materi_list_context_return_empty_when_there_is_no_materi(self):
+        self.client.login(**self.admin_credential)
+        response = self.client.get(self.url)
+
+        self.assertFalse(
+            response.context['materi_list'],
+            "Materi_list not empty when there is no materi"
+        )
+
+    def test_materi_list_context_return_correct_amount_of_materi_when_there_is_materi(self):
+        Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor,
+                                       publisher="Kelas SC", descriptions="Deskripsi Materi 1",
+                                       status="PENDING", cover=self.cover, content=self.content,
+                                       date_modified=datetime.now(), date_created=datetime.now())
+
+        Materi.objects.create(title="Materi 2", author="Agas", uploader=self.contributor,
+                                              publisher="Kelas SC", descriptions="Deskripsi Materi 2",
+                                              status="APPROVE", cover=self.cover, content=self.content,
+                                              date_modified=datetime.now(), date_created=datetime.now())
+
+        self.client.login(**self.admin_credential)        
+        response = self.client.get(self.url)
+
+        self.assertEqual(response.context['materi_list'].count(), 2)
+
+    def test_materi_list_context_return_correct_materi_when_there_is_materi(self):
+        materi = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor,
+                                       publisher="Kelas SC", descriptions="Deskripsi Materi 1",
+                                       status="PENDING", cover=self.cover, content=self.content,
+                                       date_modified=datetime.now(), date_created=datetime.now())
+
+        self.client.login(**self.admin_credential)
+        response = self.client.get(self.url)
+
+        self.assertTrue(
+            response.context['materi_list'].filter(id=materi.id), 
+            "Materi_list not including created materi"
+        )
+
+    def test_materi_list_context_not_return_materi_that_shouldnt_exists(self):
+        materi = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor,
+                                       publisher="Kelas SC", descriptions="Deskripsi Materi 1",
+                                       status="PENDING", cover=self.cover, content=self.content,
+                                       date_modified=datetime.now(), date_created=datetime.now())
+        invalid_id_materi = materi.id + 1
+
+        self.client.login(**self.admin_credential)
+        response = self.client.get(self.url)
+        self.assertFalse(
+            response.context['materi_list'].filter(id=invalid_id_materi),
+            "Materi_list including materi that should not be exists"
+        )
diff --git a/administration/urls.py b/administration/urls.py
index c13a46c75274d3aa69e5f7b7ddc8d9effbcc247c..b6970aa97471877910b11ac5ad026cb5d2b14f50 100644
--- a/administration/urls.py
+++ b/administration/urls.py
@@ -1,6 +1,15 @@
 from django.urls import path
 
-from administration.views import VerificationView, DetailVerificationView, VerificationSettingView, CategorySettingView, KelolaKontributorView, ProfileContributorAdminView, ProfileAdminAdministrationView, KelolaAdminView, RegistrasiAdminView, EditVerificationView, delete_admin, delete_contributor, delete_verification, StatisticsView, StatisticApiView, EditCategoryView, EditAdminStatusView, delete_category, generatedummy
+from administration.views import VerificationView, DetailVerificationView, \
+                                 VerificationSettingView, CategorySettingView, \
+                                 KelolaKontributorView, ProfileContributorAdminView, \
+                                 ProfileAdminAdministrationView, KelolaAdminView, \
+                                 RegistrasiAdminView, EditVerificationView, \
+                                 delete_admin, delete_contributor, \
+                                 delete_verification, StatisticsView, \
+                                 StatisticApiView, EditCategoryView, \
+                                 EditAdminStatusView, delete_category, \
+                                 generatedummy, KelolaMateriView
 
 app_name = "administration"
 
@@ -26,5 +35,6 @@ urlpatterns = [
          EditAdminStatusView.as_view(), name="edit-admin-status"),
     path("hapus-admin/<int:pk>/", delete_admin),
     path("hapus-kontributor/<int:pk>/", delete_contributor),
+    path("kelola-materi/", KelolaMateriView.as_view()),
     path("generate-dummy", generatedummy),
 ]
diff --git a/administration/views.py b/administration/views.py
index 507425066c1600ba66d2f494bf18cc594e393e56..ee97ade6000afb612d6318e07f5a4ec815b91169 100644
--- a/administration/views.py
+++ b/administration/views.py
@@ -625,4 +625,22 @@ def generatedummy(request):
     # RUn management command
     management.call_command('generatedummy', materi)
     management.call_command('generatetraffic', visitor)
-    return JsonResponse({"success":True,"materi":materi,"visitor":visitor})
\ No newline at end of file
+    return JsonResponse({"success":True,"materi":materi,"visitor":visitor})
+
+class KelolaMateriView(TemplateView):
+    template_name = "kelola_materi.html"
+
+    def dispatch(self, request, *args, **kwargs):
+        if not request.user.is_authenticated or not request.user.is_admin:
+            raise PermissionDenied(request)
+
+        return super(KelolaMateriView, self).dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        context = super(KelolaMateriView, self).get_context_data(**kwargs)
+        context['materi_list'] = Materi.objects.all()
+        return context
+
+    def get(self, request, *args, **kwargs):
+        context = self.get_context_data(**kwargs)
+        return self.render_to_response(context)
diff --git a/app/models.py b/app/models.py
index 4164b8443638d80ea89f091d476ef96ff0ce954d..39911d3e01ef2efdba9f0a661c5b0b6ce458ec9f 100644
--- a/app/models.py
+++ b/app/models.py
@@ -65,6 +65,10 @@ class Materi(models.Model):
                 published_date = report.timestamp
         return published_date
 
+    @property
+    def like_count(self):
+        count = Like.objects.filter(materi=self).count()
+        return count
 
 class Comment(models.Model):
     username = models.CharField(max_length=100)
diff --git a/app/tests.py b/app/tests.py
index 2b828d3453e63b88a2711f7fac171876054a8423..0ad4321961bcf57956c4d5c2d46249b915126db0 100644
--- a/app/tests.py
+++ b/app/tests.py
@@ -35,13 +35,9 @@ from .views import (DaftarKatalog, DashboardKontributorView, DetailMateri,
 from app.forms import SuntingProfilForm
 from app.utils.fileManagementUtil import get_random_filename, remove_image_exifdata
 
-from datetime import datetime
-
-import pandas as pd
-
-
 ERROR_403_MESSAGE = 'Kamu harus login untuk mengakses halaman ini'
 
+
 class DaftarKatalogTest(TestCase):
     def test_daftar_katalog_url_exist(self):
         url = "/"
@@ -144,8 +140,8 @@ class DetailMateriTest(TestCase):
             **self.anonymous_credential, name="Anonymous"
         )
         self.cover = SimpleUploadedFile(
-            "Cherprang_Areekul40_nJM9dGt.jpg", b"Test file")
-        self.content = SimpleUploadedFile("Bahan_PA_RKK.pdf", b"Test file")
+            "ExampleCover921.jpg", b"Test file")
+        self.content = SimpleUploadedFile("ExampleFile921.pdf", b"Test file")
 
         Materi(title="Materi 1", author="Agas", uploader=self.contributor,
                publisher="Kelas SC", descriptions="Deskripsi Materi 1",
@@ -2022,4 +2018,33 @@ class DownloadHistoryViewTest(TestCase):
         no_history_msg = "Anda belum mengunduh materi. Silahkan unduh materi yang anda butuhkan"
         response = self.client.get(self.history_url)
         resp_html = response.content.decode('utf8')
-        self.assertIn(no_history_msg, resp_html)
\ No newline at end of file
+        self.assertIn(no_history_msg, resp_html)
+
+
+class MateriModelTest(TestCase):
+    def setUp(self):
+        self.contributor = User.objects.create( 
+            email="kontributor@gov.id",
+            password="passwordtest",
+            name="kontributor",
+            is_contributor=True
+        )
+
+        self.cover = SimpleUploadedFile(
+            "ExampleCover221.jpg", b"Test file")
+        self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file")
+
+        self.materi = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor,
+                                            publisher="Kelas SC", descriptions="Deskripsi Materi 1",
+                                            status="APPROVE", cover=self.cover, content=self.content,
+                                            date_modified=datetime.now(), date_created=datetime.now())
+
+    def test_like_count_return_zero_when_there_is_no_like(self):
+        self.assertEqual(0, self.materi.like_count)
+
+    def test_like_count_return_right_value_when_there_is_like(self):
+        Like.objects.create(timestamp=datetime.now(), materi=self.materi, session_id="dummysessionid1")
+        self.assertEqual(1, self.materi.like_count)
+
+        Like.objects.create(timestamp=datetime.now(), materi=self.materi, session_id="dummysessionid2")
+        self.assertEqual(2, self.materi.like_count)