I graduated from high school in 2003 and initially worked in various local warehouse and manufacturing positions. From 2004 to 2010, I was employed at Fleetwood/Fleetwood RV (now REV Group, Inc.) in Decatur, IN, where I served as an electrician and Assistant Group Leader.
In September 2012, I relocated to Indianapolis to pursue a career in development and programming. I began with front-end development and progressively advanced to become a full-stack developer, team leader, and mentor.
My primary expertise lies in JavaScript, PHP, and MySQL, although I am passionate about continuous learning and skill development. I embrace challenges as opportunities for growth and am always eager to acquire new knowledge and techniques.
I have been married since 2016 and became a father in 2020. I have been serving as an Engineering Manager at Dotdash Meredith since July 2022.
Qualifications
-  
HTML5
95% -  
CSS3
90% -  
JS
75% -  
PHP
75% -  
DevOps
70% -  
MySQL/MariaDB
70% -  
Laravel
65% -  
WordPress
60% -  
React
60% -  
VueJS
55% -  
NodeJS
55% -  
AngularJS
40% -  
Gatsby
40% -  
Java
25% -  
Pyton
8% 
Portfolio
Code Examples
MySQL Examples
SELECT JSON_QUERY(meta_value, '$.users') AS users FROM wp_postmeta WHERE meta_key = '_facility_meta'
 SELECT post_id FROM wp_postmeta WHERE meta_key = '_facility_meta' AND JSON_CONTAINS(meta_value, 2, '$.users');
 Shell Examples
for i in **/*.mp4; do eval $(ffprobe -v quiet -show_format -of flat=s=_ -show_entries stream=duration $i); echo $i,$streams_stream_0_duration >> ~/Downloads/videos.csv; done;
 PHP Examples
class VideosController extends Controller
{
    public function create(Request $request)
    {
        $page = ($request->page) ? (int) $request->page : 1;
        $skip = ($page * 100) - 100;
        return View::make('admin.videos', [
            'pages' => ceil(count(Videos::whereNull('deleted_at')->get()) / 100),
            'page' => $page,
            'videos' => Videos::whereNull('deleted_at')->orderBy('path')->skip($skip)->take(100)->get(),
            'ratings' => Ratings::all(),
            'genres' => Genres::all()
        ]);
    }
    public function store(Request $request)
    {
        $names = $request->names;
        $ratings = $request->ratings;
        $lengths = $request->lengths;
        $genres = $request->genres;
        foreach($names as $id => $name) {
            $arr = [];
            $arr['name'] = $name;
            if($lengths[$id]) $arr['length'] = $lengths[$id];
            if($ratings[$id]) $arr['rating_id'] = $ratings[$id];
            if($genres[$id]) $arr['genre_id'] = $genres[$id];
            Videos::find($id)->update($arr);
        }
        return redirect(route('admin.videos') . '?page=' . $request->page);
    }
}
 JavaScript Examples
export default class Timer {
    constructor(element, direction) {
        this.element = element;
        this.direction = direction;
        this.init();
    }
    getTotalSeconds(startDate) {
        let startDatetime = new Date(startDate);
        let totalStartSeconds = startDatetime.getTime() / 1000;
        let nowDatetime = new Date();
        nowDatetime.setTime(nowDatetime.setTime(nowDatetime.getTime() + nowDatetime.getTimezoneOffset() * 60 * 1000));
        let totalNowSeconds = new Date(nowDatetime.getTime() + -300 * 60 * 1000).getTime() / 1000;
        return {
            'startSeconds': totalStartSeconds,
            'nowSeconds': totalNowSeconds
        };
    }
    getTotalSecondsSince() {
        let totalSecondsObj = this.getTotalSeconds(this.element.dataset.startDate);
        let totalSeconds = totalSecondsObj.nowSeconds - totalSecondsObj.startSeconds;
        return totalSeconds;
    }
    getTotalSecondsUntil() {
        let totalSecondsObj = this.getTotalSeconds();
        let totalSeconds = totalSecondsObj.startSeconds - totalSecondsObj.nowSeconds;
        return totalSeconds;
    }
    convertDateToValues() {
        let totalSeconds = 0;
        if (this.direction == 'up') {
            totalSeconds = this.getTotalSecondsSince();
        } else {
            totalSeconds = this.getTotalSecondsUntil();
        }
        let years, days, hours, minutes, seconds;
        years = days = hours = minutes = seconds = 0;
        if (totalSeconds >= 31536000) {
            years = parseInt(totalSeconds / 31536000);
        }
        days =  parseInt((totalSeconds - (years * 31536000)) / 86400);
        hours = parseInt((totalSeconds - (days * 86400) - (years * 31536000)) / 3600);
        minutes = parseInt((totalSeconds - (hours * 3600) - (days * 86400) - (years * 31536000)) / 60);
        seconds = parseInt((totalSeconds - (minutes * 60) - (hours * 3600) - (days * 86400) - (years * 31536000)) % 60);
        return {
            'years': years,
            'days': days,
            'hours': hours,
            'minutes': minutes,
            'seconds': seconds
        };
    };
    setTimes() {
        let values = this.convertDateToValues();
        let yearsSpan = this.element.querySelector('.timer__years');
        let daysSpan = this.element.querySelector('.timer__days');
        let hoursSpan = this.element.querySelector('.timer__hours');
        let minutesSpan = this.element.querySelector('.timer__minutes');
        let secondsSpan = this.element.querySelector('.timer__seconds');
        yearsSpan.innerHTML = values.years;
        daysSpan.innerHTML = values.days;
        hoursSpan.innerHTML = values.hours;
        minutesSpan.innerHTML = values.minutes;
        secondsSpan.innerHTML = values.seconds;
    }
    init() {
        this.setTimes(this.element, this.direction)
        setInterval(() => {
            this.setTimes(this.element, this.direction);
        }, 1000);
    }
}
 SCSS Examples
.about {
    padding: 20px 0;
    @media screen and (min-width: 1020px) {
        padding: 32px 0;
    }
    &.media--left {
        .about__media {
            order: 1;
            margin-bottom: 24px;
            @media screen and (min-width: 1020px) {
                margin-bottom: 0;
            }
        }
        .about__notes {
            order: 2;
        }
    }
    &.media--right {
        .about__media {
            order: 2;
        }
        .about__notes {
            order: 1;
            margin-bottom: 24px;
            @media screen and (min-width: 1020px) {
                margin-bottom: 0;
            }
        }
    }
    &__notes {
        p {
            margin: 0 0 18px;
            font-size: 18px;
            line-height: 1.6;
            letter-spacing: 1px;
            word-spacing: 8px;
        }
    }
}
 GraphQL Examples
{
  strapiHomePage {
    id
    modules {
      ... on STRAPI__COMPONENT_MODULES_PORTFOLIO {
        strapi_component
        strapi_id
        sectionTitle
        portfolioItems {
          title
          slug
          url
          featuredImage {
            alternativeText
            caption
            localFile {
              childImageSharp {
                gatsbyImageData(
                  width: 300
                  height: 300
                  placeholder: BLURRED
                  formats: [AUTO, WEBP, AVIF]
                  transformOptions: {
                    cropFocus: CENTER
                  }
                )
              }
            }
          }
        }
      }
    }
  }
}