Brian's Cabinets

Since 2015 I have worked with Brian's Cabinets, a large regional custom cabinet manufacturer, to build a web application for quoting, contracting, and internal processing of cabinetry jobs.

Building custom cabinets is a complex job. Proper quoting for a job needs to account for cabinet material, style, hardware, and many other details. This application takes everything into account and creates an accurate quote for a project. From there, Brian's Cabinets staff can generate proposal and contract paperwork, and prepare the job for internal manufacturing processes.

2023-09-12_17-52.png

Selected Features

Tech Stack

Code Samples

HTML / Angular.js

<h4>
    Room Specifications
    <a href="#" ng-disabled="froz" class="small button" ng-click="copySpecsModal()"><i class="fa fa-copy"></i> Copy specs to other rooms</a>
</h4>
<div class="specifications">
    <!-- interfaceUpdater -->
    <div
        ng-repeat="list in lists"
        ng-if="list.order > 0 && (
          (
            proj.rooms[currentRoom.index].cabinetstyleDescription !== 'BC closet system'
          ) ||
          (
            proj.rooms[currentRoom.index].cabinetstyleDescription === 'BC closet system' &&
            [
              'doorstylebase', 'doorstiles', 'doorrails', 'uppercabinetheight',
              'uppercabinetheight2', 'factorscabinets', 'finishedends', 'finishedbacks',
              'finishedbacks2', 'crownmolding', 'basecabinetbacks', 'subtops', 'factorsdoors'
            ].indexOf(list.id) === -1
          )
        )">
      <label>
        <span></span>
        <ui-select
            ng-disabled="froz"
            ng-model="proj.rooms[currentRoom.index][list.id+'Description']"
            on-select="saveCurrentRoomField(list.id+'Description', false, 'ui-select')"
>    
          <ui-select-match placeholder="Search...">
            
          </ui-select-match>
          <ui-select-choices
              repeat="item.Description as item in (list.list | filter: $select.search) track by item.id">
              
          </ui-select-choices>
        </ui-select>
      </label>
      <em ng-if="list.description == 'Finish' && proj.basic.finishSample == 'need'">
        Note: Finish sample must be approved by customer before this job can be contracted
      </em>
    </div>
</div>

Angular.js

$scope.deleteRoom = function() {
    $http
        .post('project/deleteRoom', { // Post to backend API
            idprojects: $rootScope.idprojects,
            idrooms: $scope.currentRoom.idrooms
        })
        .then(() => {
            // Remove from frontend
            $scope.proj.rooms.splice($scope.currentRoom.index, 1);

            $rootScope.log({
                summary: '[Quote] Delete Room',
                idprojects: $rootScope.idprojects,
                room: $scope.currentRoom
            });

            // Return to first room
            // This function saves the current room by default
            // (second param). I don't want to do that in this
            // case because the current room has been deleted
            $scope.setCurrentRoom($scope.proj.rooms[0], false);
            $scope.deleteRoomModalOpen = false;
            
            // Recalc project price
            $http
                .post('/pricing/calculateProjectPrice', {
                    idprojects: $rootScope.idprojects
                })
                .then(r => {
                    $scope.$parent.recalcedProjTotals = r.data;
                });
        }, (err) => { // Error
            $rootScope.errorModal = true;
            $rootScope.curError = {
                description: 'Error deleting room',
                err: err
            };
        });
};

Node.js

archiveProject(setTo, callback) {
    // Use custom RethinkDB class with utility functions
    const rethink = new Rethink(this.id, 'projects');
    rethink.fetchSingle(proj => {
        rethink.updateSingle(
            {
                id: proj.id,
                basic: {
                    archive: setTo
                }
            },
            () => {
                // Send to other frontend clients
                this.io.emit('project.archive', {
                    idprojects: this.id
                });
                callback({
                      id: this.id
                      basic: {
                          archive: setTo
                      }
                });
            }
        );
    });
}