Feat(profile): access 1/3

This commit is contained in:
minhtrannhat 2023-11-05 16:46:24 -05:00
parent 5a6e968efe
commit f9eec3ec44
Signed by: minhtrannhat
GPG Key ID: E13CFA85C53F8062
8 changed files with 305 additions and 163 deletions

View File

@ -46,7 +46,7 @@ public class AccessDBHelper extends SQLiteOpenHelper {
onCreate(db);
}
public long insertAccess(Access access) {
public long insertAccess(Access access, Context context) {
long id = -1;
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
@ -65,32 +65,34 @@ public class AccessDBHelper extends SQLiteOpenHelper {
return id;
}
public List<Access> getAccessFromProfileID(long profileID) {
public List<Access> getAccessFromProfileID(long profileID, Context context) {
List<Access> accessList = new ArrayList<>();
try (SQLiteDatabase db = this.getReadableDatabase()) {
Cursor cursor = null;
String[] columns = {"AccessId", "ProfileID", "AccessType", "Timestamp"};
String selection = "ProfileID = ?";
String[] columns = {"access_id", "profile_id", "access_type", "timestamp"};
String selection = "profile_id = ?";
String[] selectionArgs = {String.valueOf(profileID)};
String orderBy = "Timestamp";
String orderBy = "timestamp";
cursor = db.query(AccessContract.AccessEntry.TABLE_NAME, columns, selection, selectionArgs, null, null, orderBy);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
@SuppressLint("Range") int accessId = cursor.getInt(cursor.getColumnIndex(AccessContract.AccessEntry.COLUMN_NAME_ACCESS_ID));
@SuppressLint("Range") int _profileID = cursor.getInt(cursor.getColumnIndex(AccessContract.AccessEntry.COLUMN_NAME_PROFILE_ID));
@SuppressLint("Range") String accessType = cursor.getString(cursor.getColumnIndex("AccessType"));
@SuppressLint("Range") String timestampStr = cursor.getString(cursor.getColumnIndex("Timestamp"));
// int accessID = cursor.getInt(cursor.getColumnIndexOrThrow("access_id"));
int _profileID = cursor.getInt(cursor.getColumnIndexOrThrow("profile_id"));
String accessType = cursor.getString(cursor.getColumnIndexOrThrow("access_type"));
String timestamp = cursor.getString(cursor.getColumnIndexOrThrow("timestamp"));
// Parse the timestamp string into a LocalDateTime object
LocalDateTime timestamp = LocalDateTime.parse(timestampStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
// Convert the timestamp String to a Java LocalDateTime object
LocalDateTime localDateTime = LocalDateTime.parse(timestamp, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
Access access = new Access(accessId, _profileID, AccessType.matchEnum(accessType), timestamp);
// Create an Access object and add it to the list
Access access = new Access(_profileID, AccessType.matchEnum(accessType), localDateTime);
accessList.add(access);
} while (cursor.moveToNext());
}
cursor.close();

View File

@ -59,7 +59,9 @@ public class StudentProfileDBHelper extends SQLiteOpenHelper {
// row id
id = db.insertOrThrow(StudentProfileContract.StudentProfileEntry.TABLE_NAME, null, contentValues);
} catch (Exception e) {
Toast.makeText(context, "DB insert failed: " + e.getMessage(), Toast.LENGTH_LONG).show();
Toast.makeText(context, "Profile ID has to be Unique", Toast.LENGTH_LONG).show();
Log.e("StudentProfileDBHelper", "insertStudentProfile: " + e);
} finally {
db.close();
}

View File

@ -3,30 +3,18 @@ package com.example.coen390_assignment2.Models;
import java.time.LocalDateTime;
public class Access {
private int accessID;
private long profileID;
private AccessType accessType;
private LocalDateTime timestamp;
public Access(int accessID, long profileID, AccessType accessType, LocalDateTime timestamp) {
this.accessID = accessID;
public Access(long profileID, AccessType accessType, LocalDateTime timestamp) {
this.profileID = profileID;
this.accessType = accessType;
this.timestamp = timestamp;
}
public int getAccessID() {
return accessID;
}
public void setAccessID(int accessID) {
this.accessID = accessID;
}
public long getProfileID() {
return profileID;
}

View File

@ -10,11 +10,15 @@ import android.widget.Toast;
import androidx.fragment.app.DialogFragment;
import com.example.coen390_assignment2.Controllers.AccessDBHelper;
import com.example.coen390_assignment2.Controllers.StudentProfileDBHelper;
import com.example.coen390_assignment2.Models.Access;
import com.example.coen390_assignment2.Models.AccessType;
import com.example.coen390_assignment2.Models.StudentProfile;
import com.example.coen390_assignment2.R;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class InsertProfileDialogFragment extends DialogFragment {
@ -64,13 +68,18 @@ public class InsertProfileDialogFragment extends DialogFragment {
ID.isEmpty() ||
GPA.isEmpty() ||
ID.length() != 8 ||
(gpa <= 0.0f || gpa >= 4.3f))) {
(gpa < 0.0f || gpa > 4.3f))) {
long id = Long.parseLong(ID);
StudentProfile profile = new StudentProfile(surname, name, id, gpa, LocalDate.now());
Access access = new Access(id, AccessType.CREATED, LocalDateTime.now());
StudentProfileDBHelper dbHelper = new StudentProfileDBHelper(getActivity());
AccessDBHelper accessDBHelper = new AccessDBHelper(getActivity());
dbHelper.insertStudentProfile(profile, getContext());
accessDBHelper.insertAccess(access, getContext());
((MainActivity) getActivity()).onStart();

View File

@ -1,12 +1,15 @@
package com.example.coen390_assignment2.Views;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@ -66,6 +69,27 @@ public class MainActivity extends AppCompatActivity {
toolbar.setSubtitle(studentProfiles.size() + " Profiles, by " + (profileNameDisplayMode ? "Surname" : "ID") );
studentProfileList.setAdapter(adapter);
studentProfileList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Get the data associated with the clicked item
StudentProfile clickedProfile = studentProfiles.get(position);
// Create an Intent to start the ProfileActivity
Intent intent = new Intent(getApplicationContext(), ProfileActivity.class);
// pass extra data
intent.putExtra("surname", clickedProfile.getSurname());
intent.putExtra("name", clickedProfile.getName());
intent.putExtra("profileId", clickedProfile.getProfileID());
intent.putExtra("gpa", clickedProfile.getGPA());
intent.putExtra("dateCreated", clickedProfile.getProfileCreationDate().toString());
// Start the ProfileActivity
startActivity(intent);
}
});
}
@Override

View File

@ -1,16 +1,118 @@
package com.example.coen390_assignment2.Views;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.coen390_assignment2.Controllers.AccessDBHelper;
import com.example.coen390_assignment2.Models.Access;
import com.example.coen390_assignment2.R;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ProfileActivity extends AppCompatActivity {
protected Long profileId;
protected String surname, name, creationDate;
protected Float gpa;
protected TextView surnameTextView, nameTextView, IDTextView, GPATextView, ProfileCreatedTextView;
protected AccessDBHelper dbHelper;
protected Toolbar toolbar;
protected ListView accessListView;
@SuppressLint("SetTextI18n")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
dbHelper = new AccessDBHelper(getApplicationContext());
surnameTextView = findViewById(R.id.surnameTextView);
nameTextView = findViewById(R.id.nameTextView);
IDTextView = findViewById(R.id.IDTextView);
GPATextView = findViewById(R.id.GPATextView);
ProfileCreatedTextView = findViewById(R.id.ProfileCreatedTextView);
accessListView = findViewById(R.id.accessListView);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle("Profile Activity");
// Retrieve the extra data from the Intent
Intent intent = getIntent();
surname = intent.getStringExtra("surname");
name = intent.getStringExtra("name");
profileId = intent.getLongExtra("profileId", -1);
gpa = intent.getFloatExtra("gpa", -1);
creationDate = intent.getStringExtra("dateCreated");
surnameTextView.setText(surname);
nameTextView.setText(name);
IDTextView.setText(Long.toString(profileId));
GPATextView.setText(Float.toString(gpa));
ProfileCreatedTextView.setText(creationDate);
if (profileId != -1 || gpa != -1){
List<Access> accessList = dbHelper.getAccessFromProfileID(profileId, getApplicationContext());
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, accessListFromProfileIDToString(accessList));
accessListView.setAdapter(adapter);
} else {
Toast.makeText(this, "Invalid Profile ID", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onStart() {
super.onStart();
}
protected String[] accessListFromProfileIDToString(List<Access> accessList){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd @ HH:mm:ss");
List<String> formattedAccessStrings = new ArrayList<>();
for (Access access : accessList) {
String formattedAccessString = access.getTimestamp().format(formatter) + " " + access.getAccessType().getStringAccessType();
formattedAccessStrings.add(formattedAccessString);
}
// Sort the list of formatted String representations based on the timestamp
formattedAccessStrings.sort(new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
// Extract the timestamps from the strings and compare them
LocalDateTime timestamp1 = LocalDateTime.parse(s1.split(" ")[0], formatter);
LocalDateTime timestamp2 = LocalDateTime.parse(s2.split(" ")[0], formatter);
return timestamp1.compareTo(timestamp2);
}
});
// Convert the sorted formatted String list back to a String array
return formattedAccessStrings.toArray(new String[0]);
}
}

View File

@ -1,148 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme" />
android:layout_height="match_parent"
android:orientation="vertical"
android:parentActivityName=".Views.MainActivity"
app:title="Profile Activity">
<TextView
android:id="@+id/profileText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/user_profile_text"
android:paddingTop="10dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/surnameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/surname_text"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme" />
<TextView
android:id="@+id/surnameTextViewEdit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
android:id="@+id/profileText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:text="@string/user_profile_text"
android:textSize="30sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/surnameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="@string/surname_text"
android:textSize="20sp" />
<TextView
android:id="@+id/surnameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="@string/name_text"
android:textSize="20sp" />
<TextView
android:id="@+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/IDText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="@string/id_text"
android:textSize="20sp" />
<TextView
android:id="@+id/IDTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/GPAText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="@string/gpa_text"
android:textSize="20sp" />
<TextView
android:id="@+id/GPATextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/createdText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingBottom="10dp"
android:text="@string/profile_created_text"
android:textSize="20sp" />
<TextView
android:id="@+id/ProfileCreatedTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<TextView
android:id="@+id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name_text"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
android:id="@+id/AccessHistoryText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:paddingBottom="10dp"
android:text="@string/access_history"
android:textSize="20sp" />
<TextView
android:id="@+id/nameTextViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/IDText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/id_text"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
<TextView
android:id="@+id/IDTextViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/GPAText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/gpa_text"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
<TextView
android:id="@+id/GPATextViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/createdText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profile_created_text"
android:paddingBottom="10dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
<TextView
android:id="@+id/ProfileTextViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textSize="20sp" />
</LinearLayout>
<ListView
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:id="@+id/accessListView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="@+id/accessListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="10dp"
android:paddingEnd="10dp" />
</LinearLayout>

View File

@ -16,4 +16,5 @@
<string name="surname_text">Surname: </string>
<string name="cancel">Cancel</string>
<string name="save">Save</string>
<string name="access_history">Access History</string>
</resources>