CRUD for user address, password hashing and renaming column

Sixth week as an intern in Tong Hin. A lot of minor changes and implementation this week. The week start off with renaming column and tables as implementing Core Identity meant using the built in default name. After some looking and trying, the name has been renamed.

Moving off with password hashing, the concept of it is to protects a password by turning it into a different and seemingly random string of characters. After looking at articles and tutorials, I implemented it and try it out. All works well.

One of the problems I met for the week is dynamic code as the code can’t get through. After some asking, I get to understand the publishAot was the problem behind all this as I set it true. This little problem involve around a word took my time to solve as if I asked earlier would be solve sooner.

Beside that, I have also commit and push for the 2nd time of my internship. It was a bad practice and commit and push took some time to look at the code and select line by line for the correct name.

Last but not least, CRUD for addresses. Create and delete was fast but read and update took some time as mapping and modifying the code need some logic running around. Test has been done and still read and update haven’t gone through.

In summary, I have implement something new and also been solving some problems. I got to proceed the task on week 3. It feels good to see progression and the things I have done for the past weeks. Will continue to keep on learning and doing on next week.

Building a Dynamic Next.js UI with Tailwind CSS

Monday, November 18, 2024 – Last week, I focused on enhancing the user interface of a Next.js website, specifically designing a page where images serve as the main attraction. Before diving into image implementation, I first tackled the challenge of structuring the website path for this page. The goal was to create a dynamic route that incorporated multiple parameters in the URL, ensuring it was both descriptive and SEO-friendly.

To achieve this, I utilized Next.js dynamic routing by wrapping file or folder names in square brackets [segmentName]. However, since the segment combined multiple data points, I initially struggled to retrieve the data correctly. Eventually, I discovered that using Optional Catch-All Segments allowed me to retrieve multiple parameters seamlessly, resolving the issue.

With the routing set up, I shifted my focus to building a thumbnail gallery for the page. As I had limited experience with such implementations, I researched how to achieve this using Tailwind CSS. Initially, I was uncertain whether Tailwind alone could handle the task or if I needed a third-party package for pre-built components. To my surprise, Tailwind proved to be a powerful tool. Its utility-first classes enabled me to design the gallery effectively, including adding hover effects and transitions without needing JavaScript or React hooks for simple interactions. This approach helped keep the page lightweight by minimizing unnecessary client-side rendering. 

During the trial-and-error process of designing the gallery, I referred to a sample website provided by Mr. Peter and explored popular design references online to create a visually appealing layout.

For this page, I also needed icons. At first, I considered using an external icon library. However, I hesitated, as importing a library, especially one that isn’t widely used or actively maintained, might not be ideal for long-term project stability, especially since I only needed a few icons. I then found an alternative: using SVGs as components, which turned out to be a flexible and lightweight solution. By leveraging an AI tool, I generated customizable SVGs that allowed me to adjust their colors and sizes without pixelation issues. These SVGs fit seamlessly into the project.

Throughout the week, I focused on beautifying the thumbnail gallery to enhance the user experience. I implemented hover effects on the images, making interactions more engaging and visually appealing.

Internship (Week 5): Refining synchronisation workflows

Starting the first day, I have a detail discussion with my colleague about best practices for clean and effective testing strategies. It was insightful and gave me some fresh perspectives on structuring tests efficiently as these conversations and learning from others’ experiences, leaving me inspired.

Moreover, I pull the repository and merge the develop branch for both user and retail contexts. I spend time to understand about RabbitMQ’s management interface when running. I also update the MessageQueueService to include new exchanges, queues and Dead Letter Queues (DLQs) for better user synchronisation. Meanwhile, I also ensure that all related tests, controllers and commands in the retail context are updated as well which relate to the new UserInfoDto. However, I also encounter some errors during testing and spend time for debugging after the updates, but then I found out that there some typo errors and some missing part to update. I also try to update the RabbitMQ for the consumer and listener for user synchronisation. Feedback from Mr. Peter on my manual synchronisation efforts was particularly helpful, he suggested me to use hardcoded practice for some cases.

Additionally, I also discuss with my colleague in order to understand RabbitMQ’s publish and listen processes more thoroughly. This discussion help to gain clarity on transaction workflows, especially for creating and publishing messages. We try to publish a message first to the queue before consuming the message. We have try for multiple times to register a new user from the page. However, we failed to and consider that it might be a connection issues. I continue my progress on manual sync in the user context by adding relevant call API that similar in retail context. Although I encounter roadblocks in registering new retail users. Mr.Peter answered me to refer on the register file instead of the commands. I found that file, and try to continue to register new user tomorrow.

Besides that, Mr.Peter assigned me some new tasks in the progress tracker such as manual synchronisation and creating default users for both systems, while ensuring both systems will subscribes the respective events for create, update and delete operations. Handling MongoDB synchronisation for item states and transfer order logs was another critical task. Then, Mr. Peter also raised a critical question about whether our synchronisation process was unnecessarily complex. His suggestion to consider MongoDB as a shared database sparked new ideas. So, I start to explore and search about the MongoDB’s synchronisation features like change streams and note potential approaches. Also, we discussion about the approach and understand about the shared database.

In addition, I also try to continue about my manual sync for main system. I successfully call the API to compare, but stuck in registering new user for retail user, I will try to finish by tomorrow. Apart from that, I also pull the latest develop branch and merge updates from Mr.Peter. I also spend time understanding new files about MongoDB, so that I could refine the user creation and synchronisation process. I then create some files for user synchronisation on MongoDB by referring the store files. Meanwhile, I continue refining the manual synchronisation for the user context and successfully achieve a sync between the systems, it was a satisfying milestone. However, the satisfaction of reaching this point was slightly dampen by new issues reveal during testing.

Conclusion

This week was a blend of deep learning, collaboration and problem-solving while debugging errors and tackling testing challenges tested my patience. The experiences of syncing systems and brainstorming innovative approaches with Mr. Peter made it worthwhile. I am getting my knowledge in understanding of RabbitMQ and MongoDB.

Internship Week 5: Enhance Order Page UI and Create Tax Dropdown

In this week, Mr. Peter gave me a task to work on enhancing the order page. Since this page is related to many files and functions, it took me four days to complete. Firstly, I created a tax dropdown to let the user choose different types of tax rates for each item. After that, I combined it with the order page line items and tried to fix the bug that did not show the tax dynamically after selecting the desired tax rate. Additionally, I redesigned the entire order page UI and set a user default store to ensure users have a great experience using it.

Secondly, I redesigned the payment UI by adjusting the spacing between payment types and other CSS styles. I also fixed the bug that allowed users to click on full payment an unlimited number of times. I set it so that users can only click once when the pop-up window is first shown or when the amount is cleared. Afterward, I worked on fixing bugs related to payment types. For non-cash payment types, I enhanced the conditional statements to validate data integrity and correctness, ensuring that a reference number and image are required. After these fixes, users can make payments and complete orders more smoothly.

Lastly, since Mr. Peter mentioned that my solution for fixing the cookie session was incomplete, I continued to work on this problem. I had only implemented checking whether the token was still valid, but not addressing expired cookie sessions or handling network disconnections. I set a timer for 30 minutes for the cookie session, so when it expires, users are forced to log out and log in again. Since the cookie session was not being triggered when users logged in, I added a reload function to the login page to ensure that the cookie session starts after the page refreshes. For network status detection, I referred to a blog that explained real-time network detection. I set up a general alert that displays “connection lost” with a retry button until the connection is restored, preventing users from losing unsaved data. Additionally, I added a network status indicator next to the username to show if the network is connected.

In conclusion, this week, I learned many new things, such as how to change all data dynamically when part of the data changes, and how to detect network status and handle cookie session timing.

Add claims, refresh token and authorize

Fifth week as an intern in Tong Hin. After some simple implementation on last Friday to test out with the bare minimum requirement, the week start with implementing claim and necessary column for the Web project. Claiming additional user details as claims in a token helps streamline processing. It also enhance security as claiming unique value in the token.

Some continuous testing on access token was done by Monday and it works through. Continuing with refresh token on Tuesday, it is a bit different than access token. The concept of refresh token is to generate a new access token when the access token is expired as the refresh token is set to be live longer than access token. After some research and coding, it worked after testing out with access token.

Continuing with update with authorize, I need to do authorization for the update command by sending the access token together with the detail to change . If the detail of the token is not the same as the registered detail of the database, it will be denied unless it is a privileged account. I did not think of sending the access token in the body at first and after some help from Mr. Peter, the task is done.

After an amount of time of trying out new concept and try to implementing new idea in the sandbox, Mr. Peter asked me to implement in the main project instead of sandbox. Everything work through except for 1 or 2 test and will continue it on next week. It is happy to see progression.

In summary, I have done different learning and implementing on new concept for me this week. For the past 2 week, I have been doing with Core Identity, JWT token and claims. I got a better understanding of every part of the code. It is indeed happy to keep on learning and doing as after doing 1 task, there will be another task to continue.

Internship (Week 4): Compare logic and mock testing

This week, I will continue on completing the compare logic for synchronisation and the mock testings. I attempt to call the API from the retail to retrieve user details but encounter some issues. Initially, I try inserting data into the retail database and executing actions through Swagger, but the API calls consistently failed. Meanwhile, I also have no clue about how can I compare the logic, I consulted with Mr. Peter about it, he then introduced me to Postman to test API calls. He firstly guided me on calling the warehouse database to retrieve user details that we created previous week. Despite this, there were errors fetching user details, Mr. Peter decide to address these issues later that evening.

Moreover, Mr. Peter left a message of instructions for using Postman to call APIs and guided me further on API calls through Postman. After manually syncing and clicking “continue” to execute the API calls, I could retrieve the user details for both lists and specific details by ID. Following his instructions and using breakpoints, I understand how the code execute step by step. I then create a new command and handler, “SyncUser,” but encounter errors with API calls from the retail database as well. I try to debug with breakpoints but couldn’t locate the issue.

Besides that, I continue developing the compare logic, created service and controller to distinguish different function calls from user query of retail. I add two controllers to retrieve user lists and specific usernames by user ID from the warehouse. However, API calls from retail still face errors. My colleague and I try in troubleshooting but couldn’t identify the problem, so I consult Mr. Peter again. He then detected a connection error with the PostgreSQL database and guided me on debugging methods like F10 and F11 for stepping through code. Together, we identified several issues such as typos, incorrect password and capitalisation errors. After resolving these and setting PublishAot library to false, we achieved a successful connection.

Apart from that, I face challenges creating the sync command and handler. I initially try to store each call detail into a file or in a table database, and fetch the retail data and compare them foreach. But then I find out it was unnecessary, as it was only for synchronisation. With guidance from my colleague, I restructure the compare logic by deleting and redoing the sync command and handler. I try Meanwhile, my friends also encountered similar API call issues, we discussed together and found out it also a connection error. In addition, Mr. Peter advised me to keep the sync task simple and also guided me on mock testing.

Additionally, I creat a new sync command and handler, I successfully synchronise user data and implement the compare logic. I’m grateful for my colleague and Mr. Peter guidance and patience on teaching me. Mr. Peter further assisted me with mock tests and emphasised the importance of documentation for code consistency. He then recommended reading Clean Code to deepen my understanding and improve my skills.

Conclusion

This week, I focus on troubleshooting API call and connection issues between the warehouse and retail databases, working through synchronisation and compare logic for user data. With guidance from Mr. Peter and support from colleagues, I improve my debugging skills, use tools like Postman and implement effective mock testing.

SQL Querying for CRUD Operations

Last week, I continued working on CRUD operations for an API, specifically focusing on retrieving lists from a newly created entity. The task was progressing smoothly until I reached the SQL query part. As someone new to writing SQL queries, I felt uncertain about the best approach to querying across multiple databases. In my previous experience with EF Core, I could simply use the Include() function to fetch data from related tables. However, doing the same in raw SQL required a different approach.

To handle data from multiple tables, I quickly realized that JOIN statements would be essential, so I dove into learning SQL joins. Although it seemed complex initially, I found that retrieving columns from multiple tables was not as difficult as I anticipated. Using SQL joins allowed me to efficiently pull data across related tables, achieving similar functionality to what Include() provides in EF Core but with SQL-specific syntax and nuances.

After grasping the join concepts, I moved on to testing and refining the query based on errors that emerged during execution, which helped me improve the overall structure. Once the read operation was stable, I developed the create operation for the entity and wrote tests to validate it. Although this entity will have additional table relationships that shall be integrated later, the essential read and create API functionality was successfully implemented. For now, I skipped implementing a delete operation, as it doesn’t align with the entity’s purpose; however, further discussion shall be made.

Toward the end of the week, I returned to my Next.js work, focusing on SEO-friendly dynamic routing for the project. I’m exploring the updated dynamic route handling introduced in Next.js 13, which differs from previous versions. Though I haven’t achieved the desired setup yet, I plan to continue refining this next week.

Getting to use ASP.NET Core Identity

Fourth week as an intern in Tong Hin. Last Friday, Mr.Peter mention about Identity on ASP.NET Core for the testing. I do some research on it on Monday and found out that Core Identity (calling this for short term) is to create user but with more promising security. Core Identity is a membership system provided by Microsoft that handles authentication, authorization, and user management features. This give us more time to focus on the business logic than the security. It took me some time to learn and to implement it.

Due to the Web application that might grow bigger and bigger, I think it is good to implement Core Identity as it provide password hashing and able to support multiple authentication schemes, such as cookie-based, JWT, and third-party OAuth providers.

On Monday, Mr.Peter asked me to do some research on Core Identity and state the advantages between our custom user and Core Identity’s users. After that, done some experiment on the sandbox repository with Core Identity and it was all good. After sorting out some questions related to Core Identity, Mr.Peter asked me to do user creation by using AspNetUsers provided by Core Identity and using the API approach which the project have been using. Beside that, I also need to create a function that can get the token when the user logins using the API approach.

Nevertheless, token is consider a new thing for me as I have no idea how implementing that thing and how it worked in the system. After some time of research and understanding the flow, I understand that the system’s token generator is only for testing after Mr.Peter telling. This lead me to replicate and modify a similar token generator in another file to do the job.

All job was done on Friday as I done the job with fulfilling the minimum requirement to ensure that all function and testing can be achievable. After that, Mr.Peter ask me to add other column that the real system going to implement and it is the end of the week.

In summary, a new thing to learn on the start of the week. It is a week that I learnt about something new for me and might get challenging as I dig through. It is still a fun and exciting week for me as I get to know things I am new to.

Week 4 Internship : Fix Bugs and Create Stock Adjustment Page

This week, I worked on resolving bugs related to multiple alerts occurring at the same time and stacking together. I found a new component to replace the original SweetAlert2 which is the 1st generation of it , and after replacing it, the new component successfully handled errors when multiple alerts occurred simultaneously. I also solved the issue where users could still perform actions on a page after manually deleting cookies without refreshing the page. I added an interval to monitor the cookie status every 0.1 seconds. This way, if a user manually deletes cookies or if they expire, the cookie check function can detect it as quickly as possible, force the user to navigate to the login page, and prompt them to log in again.

On another day, Mr. Peter asked me to create a stock adjustment feature that would allow users to adjust the stock they want. The first UI design I presented was rejected, so I created a new UI that focused more on usability. The most complicated part was calling multiple APIs to collect data, which I then had to combine into a command that would call another API to upload the stock data. It was quite challenging for me, but after 2-3 days of effort, I successfully solved the logic and it now runs smoothly, uploading data without issues.

After that, Mr. Peter asked me to write unit tests for the stock adjustment page. If I’m still not familiar with it, I can try to enhance the order page instead. I found that the order page had many bugs, such as the last person calling the update function after clicking the create button, and issues with the delivery method that prevented orders from being created. So, next week, I will focus on fixing these issues to improve the smoothness of the POS system during order creation.

Internship (Week 3): Project Integration and Synchronisation Progress

This week I continued my work using another project context folder to continue my user projects. Mr. Peter provided me with the retail project folder which was considered to be the main project I was going to work on. I tried to add a new migration and update the database to the PostgreSQL database, and I successfully ran the swagger API. I also cloned the repository and started a new feature branch by initialising git flow. Also, when I tried to execute the user project, I noticed that the user database connection was not found or not connected. So, I asked Mr. Peter and he replied me that the project should be connected to MySQL. Then, I can also access the POS system, work with my colleagues and explore front-end and back-end applications.

In addition, I also focus on running and understanding the existing functions of the system while troubleshooting through various experiments. I use a scanner device to explore frontend and backend applications. These practical experiences helped me become more familiar with them. I continued to investigate potential errors in the system and consulted with Mr. Peter to clarify some issues. At the same time, I also wrote some API code and tried to get the data and update it into the database, but I failed.

Moreover, Mr. Peter also gave me some tasks about user dataset synchronization, such as manual and automatic synchronization. I first successfully set up a database in MySQL Workbench. However, I got some errors on the server connection, I discussed the issue with my colleague and she thought it was an issue with missing MySQL docker containers and tried adding some but still couldn’t connect. We tried to resolve the issue with YouTube by reinstalling and reconfiguring the server, but still failed, so we asked Mr. Peter about the error. Soon, he discovered the docker issue and provided me with a Docker YAML file to start. I then successfully established the MySQL database connection and was able to connect to the created database and tables. Afterwards, Mr. Peter guided me through the following tasks, although I still made some mistakes.

Mr. Peter also gave me some tasks to call the API and retrieve the users to compare the sync task logic. He also provided me the sample folder to refer writing logic tests. I’ll try to complete these tasks next week.

Conclusion

This week has been both challenging and insightful. I gained hands-on experience with applications and worked in multiple environments with different databases. However, every troubleshooting step and discussion with colleagues helped me gain the confidence to navigate complex architectures. Although I’ve encountered system errors and database connection frustrations, I’ll try my best.