diff --git a/administration/views.py b/administration/views.py
index 8f4c8158860895b3f47512630bf581a7a5fe427d..52cb59f2a4a0e4656b0d3ad0113a5533270e3a20 100644
--- a/administration/views.py
+++ b/administration/views.py
@@ -12,6 +12,7 @@ from administration.services import StatisticService, DetailVerificationService,
 from app.models import Category, Materi, ViewStatistics, DownloadStatistics, Comment, Like, LaporanMateri, AdminNotification
 from authentication.models import User
 from datetime import datetime
+from app.models import NotifikasiKontributor
 
 from administration.utils import generate_time_step
 
@@ -82,6 +83,10 @@ class DetailVerificationView(TemplateView):
         verif_report = VerificationReport(
             report=report, materi=materi, user=self.request.user, status=materi.get_status_display())
         verif_report.save()
+
+        new_kontributor_notif = NotifikasiKontributor(materi=materi, user=materi.uploader, feedback=materi.get_status_display())
+        new_kontributor_notif.save()
+
         return HttpResponseRedirect("/administration/")
 
 
@@ -585,6 +590,8 @@ def blok_materi(request, *args, **kwargs):
     if materi.status == "APPROVE" and LaporanMateri.objects.filter(is_rejected=False, materi_id=materi.id):
         materi.status = "BLOCKED"
         materi.save()
+        new_kontributor_notif = NotifikasiKontributor(materi=materi, user=materi.uploader, feedback=materi.get_status_display())
+        new_kontributor_notif.save()
 
     return HttpResponseRedirect(ADMINISTRATION_REPORT)
 
diff --git a/app/migrations/0028_notifikasikontributor.py b/app/migrations/0028_notifikasikontributor.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b198645300bae7ee7dcf9dd16dc7119de709310
--- /dev/null
+++ b/app/migrations/0028_notifikasikontributor.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.1 on 2020-10-31 16:29
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('app', '0027_readlater'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='NotifikasiKontributor',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('feedback', models.CharField(default='', max_length=20)),
+                ('materi', models.ForeignKey(max_length=120, on_delete=django.db.models.deletion.CASCADE, to='app.materi')),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0029_merge_20201101_0217.py b/app/migrations/0029_merge_20201101_0217.py
new file mode 100644
index 0000000000000000000000000000000000000000..69826d1afcfbd93ecf7643f8109e292879d785b4
--- /dev/null
+++ b/app/migrations/0029_merge_20201101_0217.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.1 on 2020-10-31 19:17
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0028_notifikasikontributor'),
+        ('app', '0028_adminnotification'),
+    ]
+
+    operations = [
+    ]
diff --git a/app/models.py b/app/models.py
index 9af91f66cb8094baf9cce6cf2b4573a98cf3ac58..536b917fc5eee5fd234dceb3419ebaf549080d02 100644
--- a/app/models.py
+++ b/app/models.py
@@ -331,5 +331,13 @@ class ReadLater(models.Model):
     class Meta:
         unique_together = ["materi", "user"]
 
+class NotifikasiKontributor(models.Model):
+    materi = models.ForeignKey(Materi, on_delete=models.CASCADE, max_length=120)
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    feedback = models.CharField(max_length=20, default="")
+    
+    def __str__(self):
+        return "Status: {}".format(self.feedback)
+
 class AdminNotification(models.Model):
     materi = models.ForeignKey(Materi, on_delete=models.CASCADE)
diff --git a/app/templates/app/includes/navigation.html b/app/templates/app/includes/navigation.html
index 956d34c1041f387dcea48b5b4febb479efe13637..b50f655fbc127d401cf1917f34e195fc55e9b0ec 100644
--- a/app/templates/app/includes/navigation.html
+++ b/app/templates/app/includes/navigation.html
@@ -11,6 +11,21 @@
     <ul class="navbar-nav ml-auto">
 
         {% if request.user.is_contributor %}
+        <li class="nav-item dropdown">
+            <a id="notifBtn" class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Notifikasi</a>
+            <div class="dropdown-menu show" aria-labelledby="notifBtn">
+                {% if kontributor_notif %}
+                    {% for notif in kontributor_notif %}
+                        <a class="dropdown-item" style="white-space: break-spaces;" href="{% url 'dashboard' %}">Materi "{{notif.materi.title}}" <br>{{ notif }}</a>
+                        <div class="dropdown-divider"></div>
+                    {% endfor %}
+                {% else %}
+                    <a class="dropdown-item disabled" href="#" style="white-space: break-spaces;">Anda tidak memiliki notifikasi baru</a>
+                {% endif %}
+              </div>
+            </a>
+        </li>
+        
         <li class="nav-item">
             <a class="nav-link" href="/dashboard/">
                 <span class="mr-2 d-none d-lg-inline text-gray-600 small">Dasbor</span>
diff --git a/app/tests.py b/app/tests.py
index 27bc5b1c74a337568b8d2ae803de2f0558b60fb8..70a6ce3257865de95350ee668681e7d027fb8c2f 100644
--- a/app/tests.py
+++ b/app/tests.py
@@ -45,7 +45,7 @@ from app.views import UploadMateriHTML, add_rating_materi
 
 from .models import (Category, Comment, DislikeComment, DownloadStatistics,
                      Like, LikeComment, Materi, Rating, RatingContributor,
-                     ReadLater, ReqMaterial, Review, ViewStatistics, AdminNotification)
+                     ReadLater, ReqMaterial, Review, ViewStatistics, AdminNotification, NotifikasiKontributor)
 from .services import DetailMateriService
 from .views import (DaftarKatalog, DashboardKontributorView, DetailMateri,
                     KatalogPerKontributorView, MateriFavorite,
@@ -4024,6 +4024,77 @@ class UploadMateriTest(TestCase):
 
         self.assertEqual(Materi.objects.count(), 1)
 
+class NotifikasiKontributorTest(TestCase):
+    def setUp(self):
+        self.client = Client()
+        self.contributor_credential = {"email": "kontributor@gov.id", "password": "passwordtest"}
+        self.contributor = get_user_model().objects.create_user(
+            **self.contributor_credential, name="Kontributor", is_contributor=True
+        )
+
+        self.admin_credential = {
+            "email": "admin@gov.id",
+            "password": "passwordtest"
+        }
+        self.admin = get_user_model().objects.create_user(
+            **self.admin_credential, name="Admin", is_admin=True)
+
+        self.setUpImage()
+        self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file")
+        self.category = Category.objects.create(id="1", name="medis", description="kategori medis")
+        VerificationSetting.objects.create(title="Kriteria 1", description="memenuhi kriteria 1", archived=False, pk=1)
+    
+    @override_settings(MEDIA_ROOT=tempfile.gettempdir())
+    def setUpImage(self):
+        self.cover = InMemoryUploadedFile(
+            BytesIO(base64.b64decode(TEST_IMAGE)),
+            field_name='tempfile',
+            name='tempfile.png',
+            content_type='image/png',
+            size=len(TEST_IMAGE),
+            charset='utf-8',
+        )
+    
+    def test_no_notification(self):
+        self.client.login(**self.contributor_credential)
+        notifs = NotifikasiKontributor.objects.filter(user=self.contributor)
+        self.assertEqual(notifs.count(), 0)
+        self.client.logout()
+
+    def test_notification(self):
+        # Client as Kontributor posting new Materi
+        self.client.login(**self.contributor_credential)
+        self.client.post(
+            "/unggah/", data={"title":"Materi 1", "author":"Agas", "publisher":"Kelas SC", "release_year":"2000",
+                                "descriptions":"Deskripsi Materi 1", 'categories':"1",
+                                "cover":self.cover, "content":self.content,
+                                "yt_video_id":"jNwz4L9MGVY"}
+        )
+        self.client.logout()
+
+        # Client as Admin disapproving the Materi
+        self.client.login(**self.admin_credential)
+        materi = Materi.objects.get(title="Materi 1", uploader=self.contributor)
+        pk_new_materi = materi.id
+        self.client.post(
+            "/administration/detail-verif/"+str(pk_new_materi)+"/", data={
+                'kriteria-1':'0','feedback':"a", 'action':"disapprove"
+            }
+        )
+        self.client.logout()
+        self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 1)
+        
+        # Client as Kontributor get notifications
+        self.client.login(**self.contributor_credential)
+        notif = NotifikasiKontributor.objects.get(materi=materi, user=self.contributor)
+        html = self.client.get("/dashboard/").content.decode("utf-8")
+        self.assertIn(str(notif), html)
+
+        # Client as Kontributor check Materi detail, and the notification should be gone
+        self.client.get("/materi/"+str(materi.id)+"/")
+        self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 0)
+
+
 class AdminNotificationTest(TestCase):
         
     def setUp(self):
diff --git a/app/views.py b/app/views.py
index bba8b37f7761fe48dedd0eba481a423f3494d1f1..12bbc08ca1ad98d48615e56838d8bd99cca6b92e 100644
--- a/app/views.py
+++ b/app/views.py
@@ -35,6 +35,7 @@ from app.models import (
     Rating, RatingContributor,
     SubmitVisitor,
     ReadLater,
+    NotifikasiKontributor,
     AdminNotification
 )
 from authentication.models import User
@@ -185,6 +186,9 @@ class DetailMateri(TemplateView):
         context["review_data"] = query_set_for_review
         context["has_liked_comment"] = has_liked
         context["has_disliked_comment"] = has_disliked
+        if request.user.is_authenticated and request.user.is_contributor:
+            opened_notif = NotifikasiKontributor.objects.filter(user=request.user, materi=context["materi_data"])
+            opened_notif.delete()
         return self.render_to_response(context=context)
 
 
diff --git a/authentication/views.py b/authentication/views.py
index c33e983e6562b3e40b242cdd54a447a0db57d7ff..852894bf99a187ed02f54d75d4014ef0929c09e9 100644
--- a/authentication/views.py
+++ b/authentication/views.py
@@ -77,3 +77,12 @@ class Login(TemplateView):
 
             return self.do_login(context, email, password, request, result)
 
+from app.models import NotifikasiKontributor
+def kontributor_notif_context(request):
+    if request.user.is_authenticated and request.user.is_contributor:
+        notifs = NotifikasiKontributor.objects.filter(user=request.user)
+        return {
+            'kontributor_notif':notifs
+        }
+    else:
+        return {}
\ No newline at end of file
diff --git a/digipus/settings.py b/digipus/settings.py
index 7b0b547da75fd98b6085d6ba54cd700c68fc4d70..149fd47d1e7cffe34bb483d82aa92296322a6614 100644
--- a/digipus/settings.py
+++ b/digipus/settings.py
@@ -81,6 +81,8 @@ TEMPLATES = [
                 "django.template.context_processors.request",
                 "django.contrib.auth.context_processors.auth",
                 "django.contrib.messages.context_processors.messages",
+                
+                "authentication.views.kontributor_notif_context"
             ],
         },
     },