My experience on my daily works... helping others ease each other

Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Saturday, April 19, 2025

Google Gen AI 5-days Intensive Course - Capstone Project - AI Food Agent by Haszeli

🍽️ NakMakanApa – A Generative AI Companion for Personalized Meal Discovery

🧠 Introduction

Every Malaysian has faced the timeless question: “Nak makan apa?” ("What do I want to eat?"). Whether you're a busy parent, a health-conscious professional, or someone simply staring at a fridge of random ingredients, deciding what to eat can be surprisingly stressful.

NakMakanApa is a Generative AI-powered food recommendation system that turns that daily dilemma into an intelligent, personalized experience. Built as part of the GenAI Intensive Course Capstone Project, this solution blends natural language understanding, image recognition, and AI-driven reasoning to guide users toward delicious, healthy, and culturally relevant meals.

🌟 What Makes NakMakanApa Special?

This isn’t just a recipe finder. NakMakanApa is a full-featured AI agent capable of:

  • 🗣️ Understanding user prompts like “saya nak makanan pedas dan sihat untuk jantung” (I want something spicy and heart-healthy)

  • 🖼️ Interpreting images of fridge contents to identify usable ingredients

  • 🧠 Personalizing meal suggestions based on preferences, health goals, and local cuisine

  • 📦 Fetching recipes via vector search and fallback to Gemini LLM if needed

  • 🧾 Generating structured summaries and advice about the meal’s health benefits

  • 📄 Exporting everything as a clean PDF or TXT document


🔧 How It Works – The Process

The project unfolds in 8 major steps:

  1. Prepare a structured recipe dataset as a DataFrame (df_recipes)

  2. Install and configure required libraries (LangChain, FAISS, Gemini SDK, YOLOv8, etc.)

  3. Allow image input – users can upload a fridge/ingredient photo

  4. Detect ingredients via YOLOv8 and match them with user preferences (multilingual supported!)

  5. Search local FAISS vector index for best recipe matches

  6. Fallback to Gemini if no good match is found, auto-updating the dataset & vector DB

  7. Summarize recipe & highlight health benefits, giving users a clear reason for the recommendation

  8. Generate PDF or TXT output, with beautiful formatting, for sharing or saving offline

Example of the screen on kaggle



💡 GenAI Capabilities Applied

CapabilityApplication
📊 Structured Output / JSON ModeRecipes returned in structured JSON: title, ingredients, steps, tags
🧠 Image UnderstandingYOLOv8 used to detect food from photos
📚 Retrieval-Augmented Generation (RAG)Blend of FAISS vector search with Gemini fallback
🔍 Vector StoreEfficient similarity search on recipes using semantic embeddings
🤖 Agents (Bonus)The system behaves like an AI agent orchestrating input parsing, generation, and summarization seamlessly

🧪 Results & Achievements

✅ Users can receive personalized meal suggestions from both text and image input
✅ Recipes include clear, AI-generated summaries explaining their health value
✅ The system handles English and Malay prompts with ease
✅ Users can export results to PDF, making meal planning effortless
✅ Every process includes robust error handling for reliability


🚀 What’s Next?

This project is just the beginning. Future enhancements include:

  • 📱 A mobile app version for everyday usage

  • 🧮 Nutritional analysis (calories, macros, allergens)

  • 🛒 Smart shopping list generation

  • 🌏 Expansion to Middle Eastern and global cuisines

  • 👩‍🍳 Community recipes and feedback-driven learning


👨‍🎓 Final Thoughts

NakMakanApa is more than a technical showcase—it’s a vision for how Generative AI can enrich daily life in culturally meaningful and health-conscious ways. By combining NLP, computer vision, RAG, and AI reasoning into a seamless user flow, we created an experience that feels human, helpful, and very Malaysian.

This project proves that AI can do more than automate tasks—it can guide, support, and inspire better living.

Share:

Wednesday, April 16, 2025

Food Discovery AI Agent

 # 🍽️ Food Discovery AI Agent (Malaysian/Asian Cuisine)

This project is a **proof-of-concept AI agent** that recommends **what to eat** and **where to go** based on:

- ✅ User preferences and dietary restrictions  

- 🕒 Time of day (e.g., lunch, dinner)  

- 🌦️ Real-time weather at your current location  

- 📍 Your destination or current location  

- 🧠 LLM-powered reasoning (OpenAI GPT-3.5)  


### 💡 How It Works

1. **User Input**: Collects dietary preferences, time, and destination

2. **Weather Fetch**: Pulls real-time weather via OpenWeather API

3. **Place Discovery**: Uses Google Places API to find nearby restaurants or hawkers

4. **LLM Reasoning**: GPT analyzes the context and filters/summarizes results

5. **Visual Map**: Recommended spots are plotted on an interactive map

6. **Export**: CSV file download available

7. **Summary Report**: Optional AI-written recap of the session


### 🔐 API Keys Required

- OpenWeatherMap

- Google Places

- OpenAI (for summary)


Built with ❤️ for Malaysian/Asian food lovers 🍜🇲🇾  

Share:

Monday, February 10, 2025

JHipster vs Vaadin vs Spring Boot - Choosing your framework

 



Java frameworks provide pre-written code and tools that simplify the development of Java applications. They handle common tasks like database interaction, web request handling, and user interface creation, allowing developers to focus on the unique logic of their applications. Frameworks promote code reusability, consistency, and best practices, ultimately speeding up development and improving application quality. They range from lightweight libraries to full-fledged platforms that dictate the structure of your application.


Which ones are suitable for you?

Okay, let’s start with a brief overview of the frameworks.

1. Spring Boot

Spring Boot is not strictly a full-stack framework in the same way as the others. It’s more accurately described as a microframework or a toolkit built on top of the larger Spring Framework. Its primary goal is to drastically simplify the setup and configuration of Spring applications. Think of Spring Boot as the express lane for Spring development.

Key Features:

  • Auto-configuration: Spring Boot automatically configures many beans (objects managed by Spring) based on dependencies in your project. This reduces the amount of manual configuration you have to do.
  • Embedded Servers: Easily embed Tomcat, Jetty, or Undertow directly into your application, making deployment simpler.
  • Spring Boot CLI: A command-line interface that further simplifies development tasks.
  • Spring Initializr: A web-based tool for quickly bootstrapping new Spring Boot projects.
  • Use Cases: Spring Boot is ideal for building REST APIs, microservices, and any backend component where you need the power and flexibility of the Spring ecosystem.

2. JHipster

JHipster takes Spring Boot and combines it with powerful code generation capabilities. It’s a full-stack application generator that helps you create modern web applications with Spring Boot on the backend and popular JavaScript frameworks (Angular, React, or Vue.js) on the front end.

Key Features:

  • Full-stack code generation: Generates both backend and frontend code, including authentication, database integration, and basic CRUD (Create, Read, Update, Delete) operations.
  • Microservices support: Can generate applications designed for a microservices architecture.
  • Blueprint architecture: Allows for customization and extension of the generated code.
  • Use Cases: JHipster is perfect for rapidly prototyping full-stack applications, especially when you want to use Spring Boot and a modern JavaScript framework. It’s less ideal for very small, simple projects where the overhead of JHipster might be too much.

3. Vaadin

Vaadin is a full-stack Java web framework focused on building rich and interactive web UIs. It offers two main approaches:

  • Vaadin Flow: Allows you to build UIs entirely in Java, without writing HTML or JavaScript directly. Vaadin handles the rendering on the client-side.
  • Hilla: A newer approach that combines a Spring Boot backend with a reactive TypeScript frontend.

Key Features:

  • Component-based architecture: UI elements are represented as reusable Java components.
  • Server-side rendering (Vaadin Flow): UI logic is executed on the server, which can simplify development for Java developers. Hilla uses client-side rendering.
  • Rich set of UI components: Vaadin provides a wide range of pre-built UI components, from simple buttons to complex grids and charts.
  • Use Cases: Vaadin is well-suited for building complex, data-driven web applications where a rich user interface is essential. It’s a good choice for Java developers who prefer a Java-centric approach to UI development.

Core Focus, Strength and Weaknesses

1. Spring Boot

  • Core Focus: This is the foundation. Spring Boot simplifies building standalone, production-ready Spring applications. It handles a lot of the boilerplate configuration, making it easier to get a Spring project up and running quickly. Think of it as the engine of your application.

Strengths:

  • Speed: Rapid development with auto-configuration and embedded servers.
  • Flexibility: Works well with various databases, cloud platforms, and other technologies.
  • Mature and Widely Used: Huge community support, extensive documentation, and a vast ecosystem of libraries.

Weaknesses:

  • Not a Full-Stack Solution: You’ll need to choose and integrate your own frontend technologies (like React, Angular, or Vue.js).
  • Learning Curve: While Spring Boot simplifies things, understanding the underlying Spring framework can still take time.

2. JHipster

  • Core Focus: A code generator that helps you quickly create full-stack web applications with Spring Boot on the backend and popular JavaScript frameworks (Angular, React, Vue.js) on the frontend.

Strengths:

  • Rapid Prototyping: Generates a complete application with authentication, database integration, and basic CRUD operations in minutes.
  • Best Practices: Uses well-established technologies and patterns.
  • Microservices Support: Can generate applications designed for a microservices architecture.

Weaknesses:

  • Complexity: Can generate a lot of code, which might be overwhelming for smaller projects or developers new to the technologies.
  • Less Control: You have less control over the initial setup compared to building everything from scratch.
  • Maintenance: Upgrading generated applications can be challenging.

3. Vaadin

  • Core Focus: A full-stack Java web framework that lets you build rich, interactive web UIs with Java. It offers two main approaches:
  • Vaadin Flow: Build UIs entirely in Java, without writing HTML or JavaScript.
  • Hilla: Combines a Spring Boot backend with a reactive TypeScript frontend.

Strengths:

  • Productivity: Vaadin Flow’s Java-centric approach can be very efficient for Java developers.
  • Type Safety: Strong type safety throughout the development process.
  • Excellent UI Components: Provides a wide range of pre-built UI components.

Weaknesses:

  • Steeper Learning Curve: Vaadin has its own way of doing things, so there’s a learning curve.
  • Less Flexibility: Compared to Spring Boot, Vaadin is more opinionated about how you structure your application.
  • Performance: Vaadin Flow’s server-side rendering can sometimes lead to performance issues in complex applications.

Share:

Saturday, December 14, 2024

Troubleshooting JEnv problem

It has been a while since I managed my development environment and as I wish to get my hands dirty again, I started to cleanup my java environment, and it turn out a mess or simply saying a mistake I did.

If your Jenv suddenly fail to work and your java environment did not change as you intended, follow the link below

1. https://github.com/jenv/jenv


Do follow steps shown and don't skip.

2. https://www.jenv.be/


Finally, I manage to get the right Java version that I need for the development.

openjdk version "23.0.1" 2024-10-15

OpenJDK Runtime Environment Homebrew (build 23.0.1)

OpenJDK 64-Bit Server VM Homebrew (build 23.0.1, mixed mode, sharing)



Share:

Monday, June 1, 2020

Reading entire URL content is really easy using R

In my good old days, reading the entire content of a website is not easy. The process of web scraping and getting the required data requires lots of programming and a few tools. A friend of mine even developed and sold the tool which he called it (during the development) as myrobot. He developed using PHP.

Now, it is much easier and one of the many ways is using R.

Here are the steps (which requires you to write ONLY two lines of code)

  1. Connect to the website using URL command
    con <- url ([the website url], “r”)
  2. Then, read the website
    x <- readLines(con)
  3. Do whatever you wish with the data. In this example, I print out the head of the website and also copy the whole content to a file.
    head(x)
    dput(x, “readFromUrlExample.html”)

There you go.

Result of the head(x) function
Snapshot of the content of the file copied into readFromUrlExamplehtml

The sample source code can be retrieved at 

https://github.com/masteramuk/LearnR-Coursera/blob/master/sample-ReadFromUrl.R

Share:

Thursday, April 2, 2020

Ontology Model for C Overflow Vulnerabilities Attack

Prepared the slide and was hoping to present at a conference. Unfortunately, due to Covid-19, it can only be shared online here.

I would like to thank all in the slide for making it through especially Saiful who give it all to complete the paper and published it at IJATCSE.

You may access and view the slide at Slideshare


#covid19 #overflow #softwaresecurity #overflowvulnerabilities #programanalysis #staticanalysis #informationsecurity #security #cybersecurity
Share:

Monday, January 13, 2020

Disruptive UI/UX - The new interactive design of a website

The faces of a website have evolved drastically from normal static one page to multiple page interactive and so on. With Big Data and ML, comes chatbot and more interactive website which more customer engaging concept.

It no time, we will definitely view a website through the Augmented Reality concept. Just read the name on a billboard, and then you will get to see the whole company profile in AR mode. Well, while waiting for this to happen, let us take a look at few revolutionize user engaging designs of a website.

As shared by Bruno Simon at https://bruno-simon.com/


Whom also the master of behind many 'abnormal' website like Orano


and Prior Holding



Go ahead browse the website and you will feel different.




Share:

Codility - PermCheck (Check whether array A is a permutation)


This is the second lesson in Codility. Given an array of integer N, you need to find if the given array is a permutation array or perfect array in sequence (if all numbers are sorted accordingly). The full explanation of the lesson is here.

It does not take me long compared to the previous lesson. I scored 100% on the first trial and here is the explanation of my code.

Since it already stated that the array starts from a positive number, I just set the expected int is 1 and missing to 0
int expectedInt = 1;
int missingInt = 0;
Then, the array is sorted accordingly. I’m using java.util.Arrays library
 Arrays.sort(A);
To find the missing int, just loop the sorted array and find the first occurrence of the missing int.
for (int x : A){ //loop to find the missing int
     if (x == expectedInt){
          expectedInt++;
     } else {
         missingInt = expectedInt;
     }
 }

This code is not perfected yet as it will continue to search despite it found the missing int. I should further improve it later. However, for codility purposes, it stops here. You can further enhance the code by implementing the break clause once found the first missing int.
The code
And here is the result. Ya, it shows 2 minutes; that is because I test it again to snapshot the result :). In actual, for a few trials, it took me around 2 hours to perfect it and scored 100%
Result

You can download the full code at
  1. Bitbucket — git clone https://masteramuk@bitbucket.org/fullstacksdev/codility-permcheck.git
  2. Github — git clone https://github.com/masteramuk/codility-lessoncode.git





Share:

Codility - FrogRiverOne (Find the earliest time when a frog can jump to the other side of a river)

This is the fourth lesson in Codility. You need to find the fastest (earliest) time possible for a frog to start jumping towards the other side of the river. You will be given an array that reflecting the position of jumping/landing point for the frog. 

The frog will start to jump when all landing point is in the right position. Two input is given; X as the final jumping position and Y array of integer. For each element in the array, every index is considered as seconds. You need to arrange the number in the array and trigger when all are in sequence with X as the last element.


It took me another 1 full day and many try-n-error to get it perfect 100%

In the beginning, I’m using 2 Array of Integer as shown below. There are few test cases that failed because the time taken to process is more than the limit given.
100% accuracy but the overall score is 18%
With an improvement in the code, I managed to improve the overall score to 54%. I managed to reduce some of the performance issues.
100% accuracy but overall score is 54%
It looks like Array.copyOf and Arrays.stream do take a longer time to process.

Another improvement has lessened the length of the code and improve the overall score to 63%
63% overall score
The code above simply set the C array to value one of the position indexes of A. Here are the list of test that it fails
▶medium_range
 arithmetic sequences, X = 5,000✘TIMEOUT ERROR
 running time: 0.112 sec., time limit: 0.100 sec.
 1.0.112 sTIMEOUT ERROR, running time: 0.112 sec., time limit: 0.100 sec.
 ▶large_random
 10 and 100 random permutation, X = ~10,000✘TIMEOUT ERROR
 running time: 1.128 sec., time limit: 0.880 sec.
 1.1.128 sTIMEOUT ERROR, running time: 1.128 sec., time limit: 0.880 sec.
 2.0.200 sOK
 ▶large_permutation
 permutation tests✘TIMEOUT ERROR
 running time: 1.716 sec., time limit: 0.880 sec.
 1.1.716 sTIMEOUT ERROR, running time: 1.716 sec., time limit: 0.880 sec.
 2.6.000 sTIMEOUT ERROR, Killed. Hard limit reached: 6.000 sec.
 ▶large_range
 arithmetic sequences, X = 30,000✘TIMEOUT ERROR
 Killed. Hard limit reached: 6.000 sec.
 1.6.000 sTIMEOUT ERROR, Killed. Hard limit reached: 6.000 sec.
I changed my strategy. Instead of using a normal Array of integer, I implement List & ArrayList.

Bad improvement - 54% overall
Instead of getting better, it is getting worse. I google on it and found that List do have performance issues and found few suggestions on it. Either use Hashmap, HashSet, TreeSet or GapList. 


I do improve the process on my laptop and surprisingly, it was way faster than List or ArrayList. Unfortunately, Codility does not support the library. Hence, I need to look for another alternative.

Based on the performance comparison between Hashmap, HashSet, and TreeSet, HashSet seems promising. And so it did. My final code is using HashSet and finally, the result shown is 100%. Here is part of the code:
1. Definition
HashSet list= new HashSet();

2. Used
           for(int idx = 0; idx < A.length; idx++){
         if ( !list.contains(A[idx]) ){
            list.add(A[idx]);
         }
         if ( list.size() == X ){
            return idx;
         }
      }

I also found a few solutions which score 100%
    This solution was shared by someone and it claims score 100/100
    public int solution(int X, int[] A) {
        int[] B = A.Distinct().ToArray();
        return (B.Length != X) ? -1 : Array.IndexOf(A, B[B.Length - 1]);
    }
    
    This solution was shared too and score 100/100 for correctness, task, and performance
    public int solution(int X, int[] A) {
        HashSet unique= new HashSet();
        for (int i = 1; i<= X; i++){
            unique.add(i);
        }
        for(int j = 0; j< A.length; j++){
            if(unique.contains(A[j])){
                unique.remove(A[j]);
                   if(unique.isEmpty()){
                         return j;
                    }
            }
        }
        return -1;
    }


Full source code is accessible at
  1. Bitbucket — git clone https://masteramuk@bitbucket.org/fullstacksdev/codility-frogriverone.git
  2. Github — git clone https://github.com/masteramuk/codility-lessoncode.git


Share:

Sunday, January 12, 2020

Codility - TapeEquilibirium (Finding the lowest difference in an array)


Given an array of int (ranging from -ve to +ve value) with the minimum number of an element is 2 and the maximum element is 100,000, you need to find the lowest difference between two sets of value (of the total sum of the array).

The actual description can be seen at Codility website (https://app.codility.com/programmers/lessons/3-time_complexity/tape_equilibrium/)

It took me 1 full day to resolve it despite the time given was only 120 minutes. On the first trial, I got 88% correct. It resolves all but two out of all test was considered as a failure due to time taken was more than expected. Next few trials, I score between 66% and 84%. The only issue was the double element array and small element array.
After a while, I figure out. The line below
int totalSum = Arrays.stream(A).sum();
is causing the time taken more than expected. Although it passed, it was 0.020 seconds more than the limit.

After a few modifications, wallawei, finally, I achieved 100%.

Snapshot of the code

Result

Full code is accessible at
  1. Bitbucket — git clone https://masteramuk@bitbucket.org/fullstacksdev/codility-tapeequilibrium.git
  2. Github — git clone https://github.com/masteramuk/codility-lessoncode.git




Share:

Saturday, January 11, 2020

Codility - PermMissingElem (Find the missing element in a given permutation)

This is a lesson in codility for the Time Complexity algorithm. Given an array of integer, you need to find the lowest missing integer.

I managed to score 100% for it.

Here is the snapshot of the code:
Based on the length, for all value in Array A, start the search and compare the initial value; that is 1 (expectedInt). If the value exists, the expectedInt is added 1 value.
                 if( A.length > 0 ){
           for (int x : A){
             //if found a value based on expected value 
             if (x == expectedInt){ 
                expectedInt++;
             } else { //if found a mising value 
                missingInt = expectedInt;
             }
           }
         }
If the Array is empty, we will just set the missingInt to 1.
        if (A.length == 0) {
          missingInt = 1;
     }
If no missing int found, then we just add additional 1 to the last value found
       if (missingInt == 0){
           missingInt = A[A.length — 1] + 1;
       }

The complete code is shown below
Codility - PermMissingElem sample code
My result is shown below
Result


You can download the code from here:

  1. Bitbucket - git clone https://masteramuk@bitbucket.org/fullstacksdev/codility-permmissingelem.git
  2. Github - git clone https://github.com/masteramuk/codility-lessoncode.git



Share:

Codility - FrogJmp (Count minimal number of jumps from position X to Y)

Codility - FrogJmp

Count the minimal number of jumps from position X to Y

FrogJmp is the third lesson number 1 out of three in the list for Time Complexity algorithm. Basically, it is an algorithm to count the number of the jump from one X location to Y location when the number of the step taken is given as Z for each single jump

public int solution(int X, int Y, int D){
        int a = 0;
        Y = Y - X; //setting the initial value test

        if (Y >= 1){ //evaluating the Y value
            a = Y/D; //setting the initial return value
            if (Y % D > 0){ //evaluating the possible number of jump to add additional value
                a++;
            }
        }
        if ( a == 0 && (Y%D==0) && Y > X ){ //final check
            a = 1;
        }
        return a;
    };

Result of the code

Code is downloadable from
Github - https://github.com/masteramuk/codility-lessoncode.git
Share:

Thursday, January 9, 2020

Codility - OddOccurrencesInArray (Find value that occurs in odd number of elements)

Given an array, find a value that has no duplication or unpaired value. I scored 100%

public int solution (int[] A){
        int a = 0;
        //sort the array
        Arrays.sort(A);
       
        int[] sortA = A;
        int x = 0;
        int cnt = 1;
        int[] oddA = new int[]{};
        //int idxOdd = 0;
       
        while ( x < sortA.length ){
            if ( x != 0 ){
                if (a == sortA[x]){
                    cnt++;
                } else {
                    if (cnt % 2 > 0){
                        oddA = Arrays.copyOf(oddA, oddA.length + 1 ); //sortA[ x - 1];
                        oddA[oddA.length - 1] = sortA [x - 1];
                    }
                    a = sortA[x];
                    cnt = 1;
                }
            } else {
                a = sortA[x];
            }
            x++;
        }
        if ( x == sortA.length && cnt == 1) {
            oddA = Arrays.copyOf(oddA, oddA.length + 1 ); //sortA[ x - 1];
            oddA[oddA.length - 1] = sortA[x - 1];
        }
        System.err.println("sortA: " + Arrays.toString(sortA) + System.lineSeparator() + "Result: " + Arrays.toString(oddA));
        return oddA[0];
    };

The code is downloadable from
Share:

Codility - CyclicRotation (Rotate an array to the right by a given number of steps)

This is the second lesson in Codility; that is to rearrange an array to the right based on the number of steps given. It will be two input and I scored 100% for it.

public int[] solution (int[] A, int K){
        int a = 0;
        int[] sortA = A;
        int x = 0;
     
        while (x < K && x < A.length){
            a = sortA[sortA.length - 1];
         
            Arrays.copyOfRange(sortA, 0, sortA.length);
            sortA = Arrays.copyOf(sortA, sortA.length);
            System.arraycopy(sortA, 0, sortA, 1, sortA.length - 1);
            sortA[0] = a;
         
            System.err.println( x + " : " + Arrays.toString(sortA) + " - " + a);
         
            x++;
        }
        return sortA;
    };


  100% CyclicRotation

You can get the code at
Bitbucket - git clone https://masteramuk@bitbucket.org/fullstacksdev/codility-cyclicrotation.git
Github - git clone https://github.com/masteramuk/codility-lessoncode.git

Share:

Codility - Find longest sequence of zeros in binary representation of an integer.

I'm taking the coding test at Codility for a job offered by a Japanese company (of which I did not get it). For practice, I tried all and this are the code (in Java) for binary gap

public int solution (int N){
//Convert the value to binary and split the value between number 1
        String s2[] = Integer.toBinaryString(N).substring(0, Integer.toBinaryString(N).lastIndexOf('1') ).split("1");
        int x = 0;
        int a = 0;
        
//find and count the longest zeros
        while(x < s2.length){
            a = a > s2[x].length() ? a : s2[x].length();
            x++;
        }
        
        System.out.println("Number: " + N + System.lineSeparator() + "Binary: " + Integer.toBinaryString(N) 
                + System.lineSeparator() + "Zero: " + a);
        return a;
    };

It score 100% for codility test.

You can download the code here
Bitbucket - git clone https://masteramuk@bitbucket.org/fullstacksdev/codility-binarygap.git
Github - git clone https://github.com/masteramuk/codility-lessoncode.git
Share:

Friday, August 31, 2018

Downloading and Formatting data for PDF output using Ionic, Angular, Cordova and TypeScript

It has been a while I did not focus and wrote anything on this blog and it is good to be back on track.

Lets kick start with writing PDF on your mobile apps. You may have data retrieve and your client require you to download the data as PDF. I've done that on Excel and it was way easy to do that.

Now lets start for PDF. It is pretty much easy too. We are going to use PDFMaker library.

If you follow the steps shows here, it shall be sufficient.

https://ionicacademy.com/create-pdf-files-ionic-pdfmake/

and you can read the entire library here

http://pdfmake.org/#/gettingstarted

You need to download and install three libraries for it to work
# Install Cordova Plugins
1. ionic cordova plugin add cordova-plugin-file-opener2
2. ionic cordova plugin add cordova-plugin-file

#Install NPM packages
3. npm install pdfmake @ionic-native/file-opener @ionic-native/file
Once complete, declare it in your apps.module.ts. The link above shall guide you with the sample.

The link above shows how it was done in a single page.  I, on the other hand, create a service provider to ease me in sharing the service between the apps. Below is the snapshot of my code... and Yup, I'm using Promise to ensure I can control the outcome and catch any error.

#the import
import { Platform } from 'ionic-angular';
//import { Http } from '@angular/http';
import { Injectable, Component } from '@angular/core';

import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;

import { File } from '@ionic-native/file';
import { FileOpener } from '@ionic-native/file-opener';

#the control
createPdf( isMin: boolean ): Promise<any>{
return new Promise ((resolve,reject) => {
if( isMin ){
this.createPdfMin()
.then((data) => {
return resolve( data );
})
.catch( (error) => {
return reject( error );
})
} else {
this.createPdfMax()
.then((data) => {
return resolve( data );
})
.catch( (error) => {
return reject( error );
})
}
})
} //end createPdf

#partial code to create pdf
createPdfMin(): Promise<any>{
//let docDefinition = null;

return new Promise((resolve) => {
let docDefinition = {
// a string or { width: number, height: number }
pageSize: 'A4',

// by default we use portrait, you can change it to landscape if you wish
pageOrientation: 'potrait',

// [left, top, right, bottom] or [horizontal, vertical] or just a number for equal margins
pageMargins: [ 10, 30, 10, 30 ],

content: [
{ text: 'The Header', style: 'header' },
{ text: new Date().toTimeString(), alignment: 'right' },
//SPA Section
{ text: 'Sub Header', style: 'subheader' },

{ text: 'Sub Sub Header', style: 'subheader2' },
{
columns: [
{
text: 'Intial data'
},
{
width: '*',
text: theValue.toLocaleString('en-US', {
style: 'currency',
currency: 'MYR',
})
}
],
// optional space between columns
columnGap: 10
},
{ text: '---------------------------------------------------', style: 'subheader2' },
],
styles: {
header: {
fontSize: 18,
bold: true,
},
subheader: {
fontSize: 14,
bold: true,
margin: [0, 15, 0, 0]
},
subheader2: {
fontSize: 12,
bold: true,
margin: [0, 15, 0, 0]
},
story: {
italic: true,
alignment: 'center',
width: '50%',
}
}
}

this.pdfObj = pdfMake.createPdf(docDefinition);

return resolve( this.pdfObj );
});
} //end createPdfMin

#code to download the pdf
downloadPdf(pdfObj, type:string):Promise<any>{
console.log('fileCreator.downloadPdf()');
return new Promise((resolve) => {
if (this.plt.is('cordova')) {
pdfObj.getBuffer((buffer) => {
var blob = new Blob([buffer], { type: 'application/pdf' });
// Save the PDF to the data Directory of our App
this.file.writeFile(this.file.dataDirectory, 'file_' + type + '.pdf', blob, { replace: true }).then(fileEntry => {
// Open the PDf with the correct OS tools
this.fileOpener.open(this.file.dataDirectory + 'file_' + type + '.pdf', 'application/pdf');
})
});
} else {
// On a browser simply use download!
this.pdfObj.download();
}
return resolve("success");
})
} //end function downloadPdf

#how it is called from other page or file
this.fileCreatorProvider.createPdf(true)
.then((data) =>{
//download the file for min
this.fileCreatorProvider.downloadPdf(data,'type')
.then((data) => {
if ( data === 'success'){
this.presentAlert('Download Complete','Successfully download the file','success');
} else {
this.presentAlert('Download Error','Fail to download the file','error');
}
})
.catch((error) => {
this.presentAlert('Download Error','Fail to download the file. Catch ' + error,'error');
})
})
.catch((error) => {
this.presentAlert('Download Error','Fail to download the file. Catch ' + error,'error');
})


and you shall be ready.

By the way, it is just snapshot. It shall give you brief idea on how to do that.

Happy Coding!!!


Share:

About Me

Somewhere, Selangor, Malaysia
An IT by profession, a beginner in photography

Labels

Blog Archive

Blogger templates