From c81310f9824dd75695252e76a76217c60de27b5a Mon Sep 17 00:00:00 2001 From: ErolHaagenrud Date: Wed, 7 Jan 2026 11:33:14 +0100 Subject: [PATCH] =?UTF-8?q?F=C3=B8r=20Oppgaver=20Steg=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kbs/kbsintranett/HomeAdapter.java | 18 +- .../com/kbs/kbsintranett/HomeFragment.java | 30 ++-- .../com/kbs/kbsintranett/MainActivity.java | 160 ++++++++---------- .../java/com/kbs/kbsintranett/TaskItem.java | 33 ++++ .../com/kbs/kbsintranett/TasksFragment.java | 49 ++++++ app/src/main/res/layout/activity_main.xml | 62 ++++--- app/src/main/res/layout/fragment_tasks.xml | 26 +++ app/src/main/res/layout/nav_header_main.xml | 33 ++++ .../main/res/navigation/mobile_navigation.xml | 37 ++-- 9 files changed, 301 insertions(+), 147 deletions(-) create mode 100644 app/src/main/java/com/kbs/kbsintranett/TaskItem.java create mode 100644 app/src/main/java/com/kbs/kbsintranett/TasksFragment.java create mode 100644 app/src/main/res/layout/fragment_tasks.xml create mode 100644 app/src/main/res/layout/nav_header_main.xml diff --git a/app/src/main/java/com/kbs/kbsintranett/HomeAdapter.java b/app/src/main/java/com/kbs/kbsintranett/HomeAdapter.java index 1a84eca..adf449c 100644 --- a/app/src/main/java/com/kbs/kbsintranett/HomeAdapter.java +++ b/app/src/main/java/com/kbs/kbsintranett/HomeAdapter.java @@ -10,7 +10,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; @@ -18,7 +17,6 @@ import java.util.List; public class HomeAdapter extends RecyclerView.Adapter { - public static final int TYPE_HEADER = 0; public static final int TYPE_CREATE_BUTTON = 1; public static final int TYPE_SECTION_TITLE = 2; public static final int TYPE_CALENDAR_ITEM = 3; @@ -44,7 +42,6 @@ public class HomeAdapter extends RecyclerView.Adapter { @Override public int getItemViewType(int position) { Object item = items.get(position); - if (item instanceof HeaderItem) return TYPE_HEADER; if (item instanceof CreateButtonItem) return TYPE_CREATE_BUTTON; if (item instanceof SectionTitleItem) return TYPE_SECTION_TITLE; if (item instanceof CalendarEvent) return TYPE_CALENDAR_ITEM; @@ -57,8 +54,6 @@ public class HomeAdapter extends RecyclerView.Adapter { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); switch (viewType) { - case TYPE_HEADER: - return new HeaderViewHolder(inflater.inflate(R.layout.item_home_header, parent, false)); case TYPE_CREATE_BUTTON: return new CreateButtonViewHolder(inflater.inflate(R.layout.item_home_create_btn, parent, false)); case TYPE_SECTION_TITLE: @@ -76,10 +71,7 @@ public class HomeAdapter extends RecyclerView.Adapter { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { Object item = items.get(position); - if (holder instanceof HeaderViewHolder) { - ((HeaderViewHolder) holder).btnProfile.setOnClickListener(v -> listener.onProfileClick()); - } - else if (holder instanceof CreateButtonViewHolder) { + if (holder instanceof CreateButtonViewHolder) { ((CreateButtonViewHolder) holder).btnCreate.setOnClickListener(v -> listener.onCreateEventClick()); } else if (holder instanceof SectionTitleViewHolder) { @@ -138,11 +130,6 @@ public class HomeAdapter extends RecyclerView.Adapter { // --- VIEW HOLDERS --- - static class HeaderViewHolder extends RecyclerView.ViewHolder { - ImageView btnProfile; - HeaderViewHolder(View v) { super(v); btnProfile = v.findViewById(R.id.btn_profile); } - } - static class CreateButtonViewHolder extends RecyclerView.ViewHolder { Button btnCreate; CreateButtonViewHolder(View v) { super(v); btnCreate = v.findViewById(R.id.btn_create_event); } @@ -179,8 +166,7 @@ public class HomeAdapter extends RecyclerView.Adapter { } } - // --- WRAPPER KLASSER FOR FLATE LISTER --- - public static class HeaderItem {} + // --- WRAPPER KLASSER --- public static class CreateButtonItem {} public static class SectionTitleItem { String title; boolean isCalendar; diff --git a/app/src/main/java/com/kbs/kbsintranett/HomeFragment.java b/app/src/main/java/com/kbs/kbsintranett/HomeFragment.java index 6c50885..4f574d0 100644 --- a/app/src/main/java/com/kbs/kbsintranett/HomeFragment.java +++ b/app/src/main/java/com/kbs/kbsintranett/HomeFragment.java @@ -173,15 +173,12 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis private void buildAndDisplayList() { List items = new ArrayList<>(); - // 1. Header - items.add(new HomeAdapter.HeaderItem()); - - // 2. Create Event Knapp (hvis tilgang) + // 1. Create Event Knapp (hvis tilgang) if (!UserManager.getInstance().getWriteableCalendars().isEmpty()) { items.add(new HomeAdapter.CreateButtonItem()); } - // 3. Kalender Seksjon + // 2. Kalender Seksjon (Redusert til 3 hendelser som avtalt) items.add(new HomeAdapter.SectionTitleItem("Kommende hendelser", true)); String today = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date()); int count = 0; @@ -193,7 +190,7 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis if (count >= 3) break; } - // 4. Nyheter Seksjon + // 3. Nyheter Seksjon items.add(new HomeAdapter.SectionTitleItem("Siste nytt", false)); items.addAll(currentNews); @@ -201,12 +198,23 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis recyclerView.setAdapter(adapter); } - // --- KLIKKHÅNDTERING (Implementert fra HomeAdapter.OnHomeClickListener) --- + // --- KLIKKHÅNDTERING --- - @Override public void onProfileClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_profile); } - @Override public void onCreateEventClick() { Navigation.findNavController(getView()).navigate(R.id.action_home_to_create_event); } - @Override public void onViewAllCalendarClick() { Navigation.findNavController(getView()).navigate(R.id.action_home_to_calendarFull); } - @Override public void onViewAllNewsClick() { Navigation.findNavController(getView()).navigate(R.id.action_home_to_newsFull); } + @Override public void onProfileClick() { + Navigation.findNavController(getView()).navigate(R.id.navigation_profile); + } + + @Override public void onCreateEventClick() { + Navigation.findNavController(getView()).navigate(R.id.action_home_to_create_event); + } + + @Override public void onViewAllCalendarClick() { + Navigation.findNavController(getView()).navigate(R.id.action_home_to_calendarFull); + } + + @Override public void onViewAllNewsClick() { + Navigation.findNavController(getView()).navigate(R.id.action_home_to_newsFull); + } @Override public void onCalendarItemClick(CalendarEvent event) { CalendarDetailsBottomSheet sheet = new CalendarDetailsBottomSheet(event); diff --git a/app/src/main/java/com/kbs/kbsintranett/MainActivity.java b/app/src/main/java/com/kbs/kbsintranett/MainActivity.java index 158c28a..8d173b1 100644 --- a/app/src/main/java/com/kbs/kbsintranett/MainActivity.java +++ b/app/src/main/java/com/kbs/kbsintranett/MainActivity.java @@ -13,28 +13,34 @@ import android.os.Bundle; import android.provider.Settings; import android.util.Log; import android.view.View; +import android.widget.TextView; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; import androidx.navigation.NavController; import androidx.navigation.fragment.NavHostFragment; +import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.google.android.gms.auth.api.signin.GoogleSignIn; import com.google.android.gms.auth.api.signin.GoogleSignInAccount; import com.google.android.gms.auth.api.signin.GoogleSignInClient; import com.google.android.gms.auth.api.signin.GoogleSignInOptions; -import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.google.android.material.navigation.NavigationView; public class MainActivity extends AppCompatActivity { public static final String GOOGLE_WEB_CLIENT_ID = BuildConfig.WEB_CLIENT_ID; - private static final String TAG = "MainActivity"; + private NavController navController; - private BottomNavigationView bottomNav; + private DrawerLayout drawerLayout; + private AppBarConfiguration appBarConfiguration; private ActivityResultLauncher requestPermissionLauncher; @@ -43,110 +49,101 @@ public class MainActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - // --- 1. SETUP UI & NAVIGASJON --- - bottomNav = findViewById(R.id.bottom_nav_view); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + drawerLayout = findViewById(R.id.drawer_layout); + NavigationView navigationView = findViewById(R.id.nav_view); NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager() .findFragmentById(R.id.nav_host_fragment); if (navHostFragment != null) { navController = navHostFragment.getNavController(); - if (bottomNav != null) { - NavigationUI.setupWithNavController(bottomNav, navController); - // Håndter "Reselection" (Klikk på fanen man allerede er i) - bottomNav.setOnItemReselectedListener(item -> { - navController.popBackStack(item.getItemId(), false); - }); - } + appBarConfiguration = new AppBarConfiguration.Builder( + R.id.navigation_home, R.id.navigation_calendar_full, R.id.navigation_tasks, + R.id.navigation_forms, R.id.navigation_news_full, R.id.navigation_handbook) + .setOpenableLayout(drawerLayout) + .build(); + + NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); + NavigationUI.setupWithNavController(navigationView, navController); - // Skjul meny på login-skjerm navController.addOnDestinationChangedListener((controller, destination, arguments) -> { - if (bottomNav == null) return; - if (destination.getId() == R.id.navigation_login) { - bottomNav.setVisibility(View.GONE); + toolbar.setVisibility(View.GONE); + drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); } else { - bottomNav.setVisibility(View.VISIBLE); + toolbar.setVisibility(View.VISIBLE); + drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); } }); } - // --- 2. VARSLINGSOPPSETT --- + updateNavHeader(navigationView); createNotificationChannel(); - - requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { - if (isGranted) { - Log.d(TAG, "Varslingstillatelse gitt!"); - } else { - Log.e(TAG, "Varslingstillatelse avslått."); - } - }); - + requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {}); checkNotificationPermission(); checkExactAlarmPermission(); - - // GAMMEL METODE FJERNET HERFRA (NotificationWorker) - - // --- 3. AUTENTISERING --- checkLoginState(); } + private void updateNavHeader(NavigationView navigationView) { + View headerView = navigationView.getHeaderView(0); + TextView name = headerView.findViewById(R.id.nav_header_name); + TextView email = headerView.findViewById(R.id.nav_header_email); + + new android.os.Handler().postDelayed(() -> { + UserManager user = UserManager.getInstance(); + if (user.isLoggedIn()) { + name.setText(user.getUserDisplayName()); + email.setText(user.getUserEmail()); + } + }, 2000); + } + + @Override + public boolean onSupportNavigateUp() { + return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp(); + } + + @Override + public void onBackPressed() { + if (drawerLayout != null && drawerLayout.isDrawerOpen(GravityCompat.START)) { + drawerLayout.closeDrawer(GravityCompat.START); + } else { + super.onBackPressed(); + } + } + private void checkLoginState() { GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); - if (account == null) { - navigateToLogin(); - } else { - refreshGoogleToken(); - } + if (account == null) navigateToLogin(); + else refreshGoogleToken(); } private void refreshGoogleToken() { GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestIdToken(GOOGLE_WEB_CLIENT_ID) - .requestEmail() - .build(); + .requestIdToken(GOOGLE_WEB_CLIENT_ID).requestEmail().build(); GoogleSignInClient client = GoogleSignIn.getClient(this, gso); - - client.silentSignIn() - .addOnSuccessListener(account -> { - String photoUrl = (account.getPhotoUrl() != null) ? account.getPhotoUrl().toString() : null; - - AuthRepository.loginToWordPress( - account.getIdToken(), - account.getDisplayName(), - account.getEmail(), - photoUrl, - new AuthRepository.AuthCallback() { - @Override - public void onSuccess(String role) { - Log.d(TAG, "Silent login fullført. Rolle: " + role); - if (navController != null && navController.getCurrentDestination() != null && - navController.getCurrentDestination().getId() == R.id.navigation_login) { - navController.navigate(R.id.action_login_to_home); - } - } - - @Override - public void onError(String message) { - Log.e(TAG, "Silent login feilet mot WP: " + message); - navigateToLogin(); - } + client.silentSignIn().addOnSuccessListener(account -> { + AuthRepository.loginToWordPress(account.getIdToken(), account.getDisplayName(), account.getEmail(), + (account.getPhotoUrl() != null ? account.getPhotoUrl().toString() : null), + new AuthRepository.AuthCallback() { + @Override public void onSuccess(String role) { + if (navController.getCurrentDestination().getId() == R.id.navigation_login) { + navController.navigate(R.id.action_login_to_home); } - ); - }) - .addOnFailureListener(e -> { - Log.e(TAG, "Silent Sign-In feilet mot Google", e); - navigateToLogin(); - }); + } + @Override public void onError(String message) { navigateToLogin(); } + }); + }).addOnFailureListener(e -> navigateToLogin()); } private void navigateToLogin() { - if (navController != null) { - if (navController.getCurrentDestination() != null && - navController.getCurrentDestination().getId() != R.id.navigation_login) { - navController.navigate(R.id.navigation_login); - } + if (navController.getCurrentDestination().getId() != R.id.navigation_login) { + navController.navigate(R.id.navigation_login); } } @@ -176,16 +173,9 @@ public class MainActivity extends AppCompatActivity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); if (alarmManager != null && !alarmManager.canScheduleExactAlarms()) { - new AlertDialog.Builder(this) - .setTitle("Varslingstillatelse kreves") - .setMessage("For at kalenderen skal kunne varsle deg nøyaktig når et møte starter, må du gi appen tilgang til å sette alarmer.") - .setPositiveButton("Gå til Innstillinger", (dialog, which) -> { - Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM); - intent.setData(Uri.parse("package:" + getPackageName())); - startActivity(intent); - }) - .setNegativeButton("Senere", null) - .show(); + Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM); + intent.setData(Uri.parse("package:" + getPackageName())); + startActivity(intent); } } } diff --git a/app/src/main/java/com/kbs/kbsintranett/TaskItem.java b/app/src/main/java/com/kbs/kbsintranett/TaskItem.java new file mode 100644 index 0000000..35c65d3 --- /dev/null +++ b/app/src/main/java/com/kbs/kbsintranett/TaskItem.java @@ -0,0 +1,33 @@ +package com.kbs.kbsintranett; + +import java.io.Serializable; +import java.util.UUID; + +public class TaskItem implements Serializable { + private String id; + private String title; + private String description; + private long dueDate; + private boolean isCompleted; + private String assignedToEmail; + private String createdByEmail; + + public TaskItem(String title, String description, long dueDate, String assignedToEmail) { + this.id = UUID.randomUUID().toString(); + this.title = title; + this.description = description; + this.dueDate = dueDate; + this.assignedToEmail = assignedToEmail; + this.createdByEmail = UserManager.getInstance().getUserEmail(); + this.isCompleted = false; + } + + // Getters og Setters + public String getId() { return id; } + public String getTitle() { return title; } + public String getDescription() { return description; } + public long getDueDate() { return dueDate; } + public boolean isCompleted() { return isCompleted; } + public void setCompleted(boolean completed) { isCompleted = completed; } + public String getAssignedToEmail() { return assignedToEmail; } +} \ No newline at end of file diff --git a/app/src/main/java/com/kbs/kbsintranett/TasksFragment.java b/app/src/main/java/com/kbs/kbsintranett/TasksFragment.java new file mode 100644 index 0000000..358d67a --- /dev/null +++ b/app/src/main/java/com/kbs/kbsintranett/TasksFragment.java @@ -0,0 +1,49 @@ +package com.kbs.kbsintranett; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import java.util.ArrayList; +import java.util.List; + +public class TasksFragment extends Fragment { + + private RecyclerView recyclerView; + private List taskList = new ArrayList<>(); + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_tasks, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + recyclerView = view.findViewById(R.id.recycler_tasks); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + + FloatingActionButton fab = view.findViewById(R.id.fab_add_task); + fab.setOnClickListener(v -> { + Toast.makeText(getContext(), "Ny oppgave-funksjon kommer her", Toast.LENGTH_SHORT).show(); + }); + + loadTasks(); + } + + private void loadTasks() { + // Dummy data + taskList.clear(); + taskList.add(new TaskItem("Husk å sjekke filter", "Serviceoppdrag hos kunde X", System.currentTimeMillis(), "meg@kbs.no")); + // Her vil vi senere koble på en TaskAdapter + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 42acff3..c9e92c4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,33 +1,49 @@ - + tools:openDrawer="start"> - + - + - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_tasks.xml b/app/src/main/res/layout/fragment_tasks.xml new file mode 100644 index 0000000..00c16b6 --- /dev/null +++ b/app/src/main/res/layout/fragment_tasks.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml new file mode 100644 index 0000000..123f5ee --- /dev/null +++ b/app/src/main/res/layout/nav_header_main.xml @@ -0,0 +1,33 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index a06fb07..2f95412 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -5,6 +5,7 @@ android:id="@+id/mobile_navigation" app:startDestination="@+id/navigation_home"> + + - + - + + android:id="@+id/navigation_tasks" + android:name="com.kbs.kbsintranett.TasksFragment" + android:label="Oppgaver" + tools:layout="@layout/fragment_tasks" /> + + + + + + android:defaultValue="0" + app:argType="integer" /> + - - +