Thursday, April 17, 2025

ReactTS: Employee Management System: ADD EMPLOYEE with VALIDATION

What are Hooks in React with TypeScript?

Hooks are functions that let you "hook into" React state and lifecycle features from function components. In TypeScript, hooks are strongly typed to provide better developer experience and type safety.


Core React Hooks:

  1. useState - Manages component state

  2. useEffect - Handles side effects

  3. useContext - Accesses context values

  4. useReducer - Manages complex state logic

  5. useCallback - Memoizes functions

  6. useMemo - Memoizes values

  7. useRef - Creates mutable references

  8. useLayoutEffect - Similar to useEffect but fires synchronously after DOM mutations


Why Use Hooks in React with TypeScript?

1. Type Safety

TypeScript adds static typing to hooks, catching errors at compile time:

2. Better Organization

Hooks allow you to organize logic by concern rather than lifecycle:

3. Reusable Logic

Custom hooks encapsulate and share logic across components:


AddEmployee.tsx component 

Imports Section




import React, { useState, useEffect, ChangeEvent, FormEvent } from "react";
// React core imports including hooks and event types

import axios from "axios";
// HTTP client for making API requests

import { Form, Button, Container, Alert } from "react-bootstrap";
// Bootstrap components for UI

import { useNavigate, Link } from "react-router-dom";
// Routing utilities for navigation

import Header from "../components/Header";
// Custom header component

import { Employee } from "../models/Employee";
import { Department } from "../models/Department";
// Type definitions for Employee and Department


Interface Definition


interface ValidationErrors {
    [key: string]: string;
}
// Defines a type for validation errors where keys are strings and values are error messages


Component Definition




const AddEmployee: React.FC = () => {
    // Main component definition as a Function Component


State Management



    
const [employee, setEmployee] = useState<Employee>({
        empId: 0,
        empName: "",
        designation: "",
        dateOfJoining: "",
        salary: 0,
        empPhoneNumber: "",
        isActive: true,
        deptId: 0
    });
    // State for employee form data, initialized with default values

    const [departments, setDepartments] = useState<Department[]>([]);
    // State for storing department list fetched from API

    const [error, setError] = useState<string>("");
    // State for general error messages

    const [validationErrors, setValidationErrors] = useState<ValidationErrors>({});
    // State for form validation errors

    const navigate = useNavigate();
    // Hook for programmatic navigation


API Configuration



   
   const EMPLOYEE_API_URL = "http://localhost:9090/api/employees";
    const DEPARTMENT_API_URL = "http://localhost:9090/api/departments";
    // API endpoint URLs


Effect Hook for Data Fetching



    
 useEffect(() => {
        const fetchDepartments = async () => {
            try {
                const response = await axios.get<Department[]>(DEPARTMENT_API_URL);
                setDepartments(response.data);
            } catch (error) {
                console.error("Error fetching departments:", error);
                setError("Failed to load departments.");
            }
        };

        fetchDepartments();
    }, []);
    // Fetches departments on component mount and stores them in state


Form Validation



    
       const validateForm = (): boolean => {
        const errors: ValidationErrors = {};

        if (!employee.empName.trim()) errors.empName = "Name is required.";
        if (!employee.designation.trim()) errors.designation = "Designation is required.";
        if (!employee.dateOfJoining) errors.dateOfJoining = "Date of Joining is required.";
        if (employee.salary <= 0) errors.salary = "Salary must be greater than 0.";
        if (!employee.empPhoneNumber.trim()) {
            errors.empPhoneNumber = "Phone Number is required.";
        } else if (!/^\d{10}$/.test(employee.empPhoneNumber)) {
            errors.empPhoneNumber = "Phone Number must be 10 digits.";
        }
        if (!employee.deptId) errors.deptId = "Department is required.";

        setValidationErrors(errors);
        return Object.keys(errors).length === 0;
    };
    // Validates form fields and returns true if all validations pass


Form Submission Handler



 
   const handleSubmit = async (e: FormEvent) => {
        e.preventDefault();
        if (!validateForm()) return;

        try {
            const response = await axios.post(EMPLOYEE_API_URL, employee);
            if (response.status === 200 || response.status === 201) {
                navigate("/");
            }
        } catch (error) {
            setError("Error adding employee. Please try again.");
            console.error("Error adding employee:", error);
        }
    };
    // Handles form submission, validates, sends data to API, and navigates on success


Input Change Handlers



    
       const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const { name, value, type } = e.target;

        setEmployee((prev) => ({
            ...prev,
            [name]: type === "number" ? Number(value) : value,
        }));

        setValidationErrors((prev) => ({
            ...prev,
            [name]: "",
        }));
    };
    // Handles changes for input fields, converts to number if needed, clears validation errors

    const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
        const { name, value } = e.target;

        setEmployee((prev) => ({
            ...prev,
            [name]: Number(value),
        }));

        setValidationErrors((prev) => ({
            ...prev,
            [name]: "",
        }));
    };
    // Handles changes for select fields, converts value to number, clears validation errors


User Data (Hardcoded for Demo)



    
   const user = "Sanjay";
    // Hardcoded user name for demo purposes


JSX Rendering



   
  return (
        <div className="container-fluid mt-4">
            <div className="card shadow p-4">
                <Header loginName={user} />
                <Container>
                    <div className="d-flex justify-content-between align-items-center mb-4">
                        <h1>Add Employee</h1>
                        <Link to="/" className="btn btn-secondary">
                            <i className="fas fa-arrow-left"></i> Employees List
                        </Link>
                    </div>

                    {error && <Alert variant="danger">{error}</Alert>}

                    <Form onSubmit={handleSubmit}>
                        {/* Form fields for each employee property */}
                        {/* Each field includes validation feedback */}

                        {/* Name Field */}
                        <Form.Group className="mb-3">
                            <Form.Label>Name</Form.Label>
                            <Form.Control
                                type="text"
                                name="empName"
                                value={employee.empName}
                                onChange={handleInputChange}
                                isInvalid={!!validationErrors.empName}
                            />
                            <Form.Control.Feedback type="invalid">
                                {validationErrors.empName}
                            </Form.Control.Feedback>
                        </Form.Group>

                        {/* Other form fields follow similar pattern */}
                        {/* Designation, Date of Joining, Salary, Phone, Department, Active Status */}

                        {/* Submit Button */}
                        <Button variant="primary" type="submit">
                            Save Employee
                        </Button>
                    </Form>
                </Container>
            </div>
        </div>
    );
};

export default AddEmployee;


Key Features:

  1. Type Safety: Uses TypeScript interfaces for Employee and Department

  2. Form Validation: Client-side validation with clear error messages

  3. API Integration: Fetches departments and posts new employee data

  4. Error Handling: Catches and displays API errors

  5. Routing: Uses React Router for navigation

  6. Bootstrap UI: Clean, responsive form layout with Bootstrap components

  7. State Management: Uses React hooks for all state needs

  8. Modular Design: Separates concerns with clear component structure

Wednesday, April 16, 2025

11 - ICT: SOUIND AND VIDEO EDITING

 1. Find out what the resolution is for 4K.

3840 × 2160 pixels (or 4096 × 2160 in the movie industry).

2. Find out why black bars are sometimes added to the top or sides of a video

Black bars are sometimes added to make a video the correct aspect ratio for the screen. If the video is a different aspect ratio to the screen, the black bars will fill the empty parts of the screen.

3. Find out which video file formats are suitable for the web. 

Formats could include: 

 • MP4 

 • MOV 

 • AVI 

 • FLV. 

4. Find out whether the file formats for the web use lossy or lossless compression.

Compression methods are: 

• MP4 – lossy 

• MOV – lossy 

• AVI – can be both 

• FLV – lossy

5 a Calculate the size of a file in megabytes (MB) that is two minutes in length, has a sample rate of 44.1 kHz and a sample resolution of 16-bit. 


To calculate the size of an uncompressed audio file (like a WAV file), we use the following formula:

File Size (bytes)=Sample Rate (Hz)×Bit Depth (bits)×Channels×Duration (seconds)

I'll assume stereo (2 channels), which is standard for most audio files.

Given:

  • Duration: 2 minutes = 120 seconds

  • Sample Rate: 44.1 kHz = 44,100 samples per second

  • Bit Depth (Sample Resolution): 16 bits per sample

  • Channels: 2 (stereo)

Step 1: Calculate File Size in Bits

Size (bits)=44,100Hz×16bits×2channels×120seconds=44,100×16×2×120=169,344,000bits

Step 2: Convert to Bytes (1 Byte = 8 Bits)

Size (bytes)=169,344,0008=21,168,000bytes

Step 3: Convert to Megabytes (1 MB = 1,048,576 Bytes)

Size (MB)=21,168,0001,048,57620.19MB

Final Answer:

2-minute stereo audio file with a 44.1 kHz sample rate and 16-bit resolution is approximately 20.19 MB in uncompressed (WAV) format.

    • If you meant binary megabytes (MiB), the answer is 10.09 MB.

  • If you meant decimal megabytes (MB), the answer is 10.58 MB.


 b Compare the file size if the sample resolution is increased to 32-bits. As size is an important factor when streaming or downloading music, sound files are often compressed.

It increases to 21.17 MB, so it doubles in size.

EXAM-STYLE QUESTIONS 

 1 Define what is meant by the aspect ratio of a video. [1] 

The proportion of a screen or video width to its height

 2 State why a trimming tool would be used on a video clip. [1] 

One from the following [1]: 

 • The video clip may be too long. 

 • To remove part of the video clip.

 3 Explain two advantages of using captions on a video clip. [2] 

Both of the following [2]: 

 • They can be used to provide further information about the image or video shown. 

 • They can be used to provide further information about where a user can learn more about the context of the image or video.

 4 Explain two advantages of using a lossy compression method on a video file. [2] 

Both of the following [2]: 

 • It makes the video file smaller, so it is quicker to download / stream. 

 • It makes the video file smaller to it takes less storage space.

 5 Explain one disadvantage of using a lossless compression method on a sound file. [1] 

It will not reduce the file size as much as lossy, so it will take up more storage space [1].

 6 Explain what is meant by the sample rate of a sound file and how it affects the file size. [2]

Both of the following [2]: 

 • The sample rate is the number of times sound is sampled in a second. 

 • If the sample rate is increased, it will increase the overall size of the file