Skip to content

Commit

Permalink
Extended Timeline, Revised Project, Experience, & Education Details
Browse files Browse the repository at this point in the history
  • Loading branch information
PLGuerraDesigns committed May 3, 2024
1 parent 48da760 commit fad3c2d
Show file tree
Hide file tree
Showing 17 changed files with 497 additions and 147 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.3.0

- NEW: Timeline section on home page now includes projects.
- NEW: The list of timeline entries can be filtered by type.
- NEW: Added a count of the number of timeline entries.

## 2.2.1

- FIX: Fixed issue with swiping between media items in the media player not updating the player banner details.
Expand Down
Binary file added assets/images/home/sjc_logo.webp
Binary file not shown.
38 changes: 38 additions & 0 deletions assets/json/education.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"school": "George Mason University",
"degree": "M.S. in Software Engineering",
"location": "Virginia, USA",
"startDate": "2022-08-01T00:00:00Z",
"endDate": "2024-05-09T00:00:00Z",
"logo": "gmu_logo.webp",
"url": "https://catalog.gmu.edu/colleges-schools/engineering-computing/school-computing/computer-science/software-engineering-ms/"
},
{
"school": "University of Arkansas",
"degree": "B.S. in Computer Science (Transfer)",
"location": "Arkansas, USA",
"startDate": "2017-08-01T00:00:00Z",
"endDate": "2020-12-01T00:00:00Z",
"logo": "uark_logo.webp",
"url": "https://catalog.uark.edu/plangrids/computerscience_bs/"
},
{
"school": "St. John's Junior College",
"degree": "Associate Degree in Computer Science",
"location": "Belize City, Belize",
"startDate": "2014-06-16T00:00:00Z",
"endDate": "2017-05-17T00:00:00Z",
"logo": "sjc_logo.webp",
"url": "https://www.sjc.edu.bz/jcacademics"
},
{
"school": "St. John's College",
"degree": "High School Diploma",
"location": "Belize City, Belize",
"startDate": "2010-08-01T00:00:00Z",
"endDate": "2014-05-17T00:00:00Z",
"logo": "sjc_logo.webp",
"url": "https://www.sjc.edu.bz/academics"
}
]
10 changes: 5 additions & 5 deletions assets/json/professional_experience.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
}
],
"externalLinks": [
{
"title": "AIC Mobile App Support",
"url": "https://aic-support.web.app"
},
{
"title": "Download on the App Store",
"url": "https://apps.apple.com/us/app/aic-mobile-app/id1534979546"
Expand All @@ -43,10 +47,6 @@
"title": "Get it on Google Play",
"url": "https://play.google.com/store/apps/details?id=com.aicbelize.AIMobile"
},
{
"title": "AIC Mobile App Support",
"url": "https://aic-support.web.app"
},
{
"title": "Atlantic Insurance Company Ltd.",
"url": "https://aicbelize.azurewebsites.net/"
Expand Down Expand Up @@ -251,7 +251,7 @@
]
},
{
"company": "AM³ Lab",
"company": "University of Arkansas (AM³ Lab)",
"folderName": "am3_lab",
"role": "Graduate Research Assistant",
"location": "Fayetteville, AR",
Expand Down
18 changes: 9 additions & 9 deletions assets/json/projects.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@
{
"title": "Flutter Resume Builder",
"subtitle": "Resume Builder Progressive Web App",
"startDate": "2022-06-03T00:00:00Z",
"startDate": "2022-10-06T00:00:00Z",
"finalDate": "2023-10-13T00:00:00Z",
"description": "The Flutter Resume Builder, created by Pablo L. Guerra, is a user-friendly, open-source progressive web application designed to simplify creating professional resumes. This innovative tool enables users to effortlessly build, edit, and customize their resumes, ensuring they are polished and impactful. With the ability to create, edit, download in both PDF and JSON formats, and import existing resumes, the Flutter Resume Builder offers a comprehensive solution for individuals seeking to craft and maintain their professional documents with ease. Whether you are a job seeker looking to streamline your resume-building process or a developer interested in the project, this platform provides an intuitive and accessible tool for crafting compelling resumes.",
"description": "The Flutter Resume Builder is a user-friendly, open-source progressive web application designed to simplify creating professional resumes. This innovative tool enables users to effortlessly build, edit, and customize their resumes, ensuring they are polished and impactful. With the ability to create, edit, download in both PDF and JSON formats, and import existing resumes, the Flutter Resume Builder offers a comprehensive solution for individuals seeking to craft and maintain their professional documents with ease. Whether you are a job seeker looking to streamline your resume-building process or a developer interested in the project, this platform provides an intuitive and accessible tool for crafting compelling resumes.",
"media": [
{
"type": "localImage",
Expand Down Expand Up @@ -359,7 +359,7 @@
{
"title": "AMG GT3 Wheel",
"subtitle": "A 3D-Printable Wheel Kit",
"startDate": null,
"startDate": "2018-10-01T00:00:00Z",
"finalDate": "2018-10-01T00:00:00Z",
"description": "The goal of the AMG GT3 Wheel project was to design and build a functional, 3D-printed replica of the Mercedes Benz AMG GT3 steering wheel for use in Sim Racing.\n\nAn Arduino Nano powers the wheel and features a thumb-slide joystick, eight pushbuttons, and a pair of paddle shifters. The wheel is directly compatible with the Thrustmaster ecosystem.\n\nYou can find the 3D-printable files on Thingiverse along with an assembly manual, circuit files, and Arduino code.",
"media": [
Expand Down Expand Up @@ -556,7 +556,7 @@
{
"title": "Apple Charging Station",
"subtitle": "3-in-1 Charging Station",
"startDate": null,
"startDate": "2019-01-01T00:00:00Z",
"finalDate": "2019-01-01T00:00:00Z",
"description": "The Apple Charging Station, initially sketched in 2016, was later revived and given as a gift to a friend.\n\nRedesigned in Autodesk Fusion 360, printed using wood-infused PLA, and finished with a wood stain. Supports charging of an iPhone, Apple Watch, and the original AirPods. The charging modules are interchangeable to support different product dimensions.",
"media": [
Expand Down Expand Up @@ -657,7 +657,7 @@
{
"title": "Switch Speaker",
"subtitle": "Nintendo Switch Speaker Attachment",
"startDate": null,
"startDate": "2019-02-01T00:00:00Z",
"finalDate": "2019-02-01T00:00:00Z",
"description": "The goal of the Nintendo Switch speaker project was to design and build a speaker attachment that would be louder than the Switch's built-in speakers.\n\nThe attachment features a 3.5mm audio plug, dual mini oval speakers, a rechargeable LiPo battery, a micro USB charging port, sliding power switch, power LED, and charging status LED.",
"media": [
Expand Down Expand Up @@ -1061,8 +1061,8 @@
{
"title": "Android Calculator",
"subtitle": "Calculator App for Android",
"startDate": null,
"finalDate": "2018-09-01T00:00:00Z",
"startDate": "2019-09-01T00:00:00Z",
"finalDate": "2019-09-01T00:00:00Z",
"description": "Android Calculator is a calculator app developed for a mobile programming class assignment at the University of Arkansas.\n\nThe app was designed in Photoshop using popular calculator apps for design reference, then programmed in Java using Android Studio.",
"media": [
{
Expand Down Expand Up @@ -1098,7 +1098,7 @@
{
"title": "Macro Pad",
"subtitle": "Programmable Macro Pad (HID)",
"startDate": null,
"startDate": "2019-04-01T00:00:00Z",
"finalDate": "2019-04-01T00:00:00Z",
"description": "Macro Pad is a programmable interface used for executing custom macros (button combinations or input sequences). It allows for extended control and execution of complex commands with a single button press.\n\nThe device features an Arduino Micro, 16 Cherry MX switches, a rotatable and pressable knob, and a micro USB port for connecting.",
"media": [
Expand Down Expand Up @@ -1136,7 +1136,7 @@
{
"title": "LED Wall Decor",
"subtitle": "Smart LED Wall Decor",
"startDate": null,
"startDate": "2019-02-01T00:00:00Z",
"finalDate": "2019-02-01T00:00:00Z",
"description": "The LED wall decor was made as an art piece for a friend. The signs' colors and patterns are controllable using the Blynk app.\n\nIt features an Arduino MKR1000 controlling eight RGB LEDs and connects to the internet using its onboard WiFi module. The LED cover plate is interchangeable using magnets. A USB micro cable is used for continuous power, but the device can also be powered using a 3.7V LiPo battery and charged with the MKR's onboard charging circuit. One of the LEDs was not working at the time the photos were taken.",
"media": [
Expand Down
15 changes: 8 additions & 7 deletions lib/common/strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Strings {
Strings._();

static const String currentLocation = 'VA, USA';
static const String lastUpdated = 'Updated APR 2024';
static const String lastUpdated = 'Updated MAY 2024';

// Routes
static const String loadingRoute = '/loading';
Expand All @@ -19,13 +19,10 @@ class Strings {
static const String thingiverseUrl =
'https://www.thingiverse.com/plg_designs/designs';
static const String linkedinUrl = 'https://www.linkedin.com/in/plguerra/';
static const String gmuUrl =
'https://catalog.gmu.edu/colleges-schools/engineering-computing/school-computing/computer-science/software-engineering-ms/';
static const String aicUrl = 'https://aicbelize.com/AIC-Mobile-App';
static const String ambotsUrl = 'https://www.ambots.net/';
static const String am3LabUrl = 'https://wordpressua.uark.edu/am3/';
static const String uarkUrl =
'https://catalog.uark.edu/plangrids/computerscience_bs/';

static const String issuesUrl =
'https://github.com/PLGuerraDesigns/portfolio/issues';
static const String contactEmailUrl = 'mailto:plguerra@outlook.com';
Expand All @@ -38,6 +35,7 @@ class Strings {
static const String projectsJsonPath = 'assets/json/projects.json';
static const String professionalExperienceJsonPath =
'assets/json/professional_experience.json';
static const String educationJsonPath = 'assets/json/education.json';
static const String socialAssetsBasePath = 'assets/images/icons';
static const String resumeBuilderIconPath =
'$socialAssetsBasePath/resume_builder.webp';
Expand All @@ -47,12 +45,10 @@ class Strings {
'assets/images/home/professional.webp';
static const String personalExperiencePhotoPath =
'assets/images/home/personal.webp';
static const String gmuLogoPath = 'assets/images/home/gmu_logo.webp';
static const String aicLogoPath =
'assets/images/professional/atlantic_insurance/logo.webp';
static const String ambotsLogoPath =
'assets/images/professional/ambots/logo.webp';
static const String uarkLogoPath = 'assets/images/home/uark_logo.webp';

// General
static const String github = 'GitHub';
Expand All @@ -67,6 +63,7 @@ class Strings {
static const String professional = 'Professional';
static const String personal = 'Personal';
static const String projects = 'Projects';
static const String education = 'Education';
static const String or = 'or';
static const String toggleBrightness = 'Toggle the Brightness';
static const String youTubeVideos = 'YouTube Videos';
Expand All @@ -91,4 +88,8 @@ class Strings {
static const String looksLikeSomethingWentWrong =
'Looks like something went wrong.';
static const String goToTheHomePage = 'Go to the Home Page';
static const String entries = 'Entries';
static const String selectACategoryToViewTheEntries =
'Select a category to view the entries.';
static const String expected = 'Expected';
}
118 changes: 102 additions & 16 deletions lib/models/app_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import '../common/strings.dart';
import '../widgets/time_line_entry.dart';
import 'education.dart';
import 'professional_experience.dart';
import 'projects.dart';
import 'project.dart';

/// The application state.
class AppState extends ChangeNotifier {
Expand All @@ -17,22 +19,32 @@ class AppState extends ChangeNotifier {

bool get mediaBrowserVisible => _mediaBrowserVisible;

/// Whether the projects have been loaded.
bool projectsLoaded = false;

/// Whether the professional experiences have been loaded.
bool professionalExperiencesLoaded = false;

/// The navigator key.
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

/// The navigator key.
GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;

/// Whether the projects have been loaded.
bool _projectsLoaded = false;
bool get projectsLoaded => _projectsLoaded;

/// The list of projects.
List<Project> get projects => _projects;
List<Project> _projects = <Project>[];

/// Whether the professional experiences are visible in the timeline.
bool _professionalExperiencesVisible = true;
bool get professionalExperiencesVisible => _professionalExperiencesVisible;

/// Whether the projects are visible in the timeline.
bool _projectsVisible = false;
bool get projectsVisible => _projectsVisible;

/// Whether the education is visible in the timeline.
bool _educationVisible = true;
bool get educationVisible => _educationVisible;

/// Returns the project with the given title as a path.
Project getProjectByTitlePath(String titleAsPath) {
for (final Project project in _projects) {
Expand All @@ -43,6 +55,9 @@ class AppState extends ChangeNotifier {
throw Exception('Project not found.');
}

/// Whether the professional experiences have been loaded.
bool professionalExperiencesLoaded = false;

/// The list of professional experiences.
List<ProfessionalExperience> get professionalExperiences =>
_professionalExperiences;
Expand All @@ -61,11 +76,33 @@ class AppState extends ChangeNotifier {
throw Exception('Professional experience not found.');
}

/// Whether the education has been loaded.
bool _educationLoaded = false;
bool get educationLoaded => _educationLoaded;

/// The list of education.
List<Education> get education => _education;
List<Education> _education = <Education>[];

/// Loads the education from the JSON file.
Future<void> loadEducation() async {
_education = <Education>[];
await rootBundle.loadString(Strings.educationJsonPath).then(
(String data) {
final dynamic jsonResult = json.decode(data);
for (final dynamic education in jsonResult as List<dynamic>) {
_education.add(Education.fromJson(education as Map<String, dynamic>));
}
},
);
_education.sort((Education a, Education b) {
return b.startDate.compareTo(a.startDate);
});
_educationLoaded = true;
}

/// Loads the projects from the JSON file.
Future<void> loadProjects(BuildContext context) async {
if (projectsLoaded) {
return;
}
Future<void> loadProjects() async {
_projects = <Project>[];
await rootBundle.loadString(Strings.projectsJsonPath).then(
(String data) {
Expand All @@ -75,14 +112,14 @@ class AppState extends ChangeNotifier {
}
},
);
projectsLoaded = true;
_projects.sort((Project a, Project b) {
return b.startDate.compareTo(a.startDate);
});
_projectsLoaded = true;
}

/// Loads the professional experiences from the JSON file.
Future<void> loadProfessionalExperiences(BuildContext context) async {
if (professionalExperiencesLoaded) {
return;
}
Future<void> loadProfessionalExperiences() async {
_professionalExperiences = <ProfessionalExperience>[];
await rootBundle.loadString(Strings.professionalExperienceJsonPath).then(
(String data) {
Expand All @@ -94,9 +131,40 @@ class AppState extends ChangeNotifier {
}
},
);

_professionalExperiences
.sort((ProfessionalExperience a, ProfessionalExperience b) {
return b.startDate.compareTo(a.startDate);
});

professionalExperiencesLoaded = true;
}

/// Loads the timeline entries.
Future<List<TimelineEntry>> loadTimelineEntries() async {
final List<TimelineEntry> entries = <TimelineEntry>[];

await loadProfessionalExperiences();
if (_professionalExperiencesVisible) {
entries.addAll(_professionalExperiences.map(
(ProfessionalExperience professionalExperience) =>
professionalExperience.timelineEntry));
}

await loadEducation();
if (_educationVisible) {
entries.addAll(
_education.map((Education education) => education.timelineEntry));
}

await loadProjects();
if (_projectsVisible) {
entries.addAll(_projects.map((Project project) => project.timelineEntry));
}

return entries;
}

/// Toggles the visibility of the media browser.
void toggleMediaBrowserVisibility() {
_mediaBrowserVisible = !_mediaBrowserVisible;
Expand Down Expand Up @@ -167,4 +235,22 @@ class AppState extends ChangeNotifier {
}
return _projects[index + 1].titleAsPath;
}

/// Toggles the visibility of the professional experiences.
void toggleProfessionalExperienceVisibility() {
_professionalExperiencesVisible = !_professionalExperiencesVisible;
notifyListeners();
}

/// Toggles the visibility of the projects.
void toggleProjectsVisibility() {
_projectsVisible = !_projectsVisible;
notifyListeners();
}

/// Toggles the visibility of the education.
void toggleEducationVisibility() {
_educationVisible = !_educationVisible;
notifyListeners();
}
}
Loading

0 comments on commit fad3c2d

Please sign in to comment.