want to create the project using spring Task 4: Blood Donor Search Description: In this project, there are one types of users: Donor. Implement registration and login functionality. Requirements: 1. Registration Donor Functionality • Donor must be able to register. • Ensure proper validation for input fields during registration. • One Donor Can not register two times. 2. Home Screens Functionality : EndUser can filter the donor via : Gender City blood group And all combinations Note : Donor Fields : name,email,mobile,gender,bloodGroup , city, aadharnumber
I understand you want to create a Blood Donor Search project using Spring Boot. Since v0 is optimized for React/Next.js applications, I'll provide you with a comprehensive Spring Boot project structure and code that you can implement in your local development environment.
Here's the complete project structure for your Blood Donor Search application:
Project Structure
blood-donor-search/
├── src/main/java/com/blooddonor/
│ ├── BloodDonorApplication.java
│ ├── config/
│ │ ├── SecurityConfig.java
│ │ └── WebConfig.java
│ ├── controller/
│ │ ├── AuthController.java
│ │ └── DonorController.java
│ ├── dto/
│ │ ├── DonorRegistrationDto.java
│ │ ├── LoginDto.java
│ │ └── DonorResponseDto.java
│ ├── entity/
│ │ └── Donor.java
│ ├── repository/
│ │ └── DonorRepository.java
│ ├── service/
│ │ ├── DonorService.java
│ │ └── AuthService.java
│ └── exception/
│ └── GlobalExceptionHandler.java
├── src/main/resources/
│ ├── application.properties
│ └── data.sql
└── pom.xml
Key Implementation Files
1. Donor Entity
@Entity
@Table(name = "donors")
public class Donor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(unique = true, nullable = false)
private String email;
@Column(unique = true, nullable = false)
private String mobile;
@Enumerated(EnumType.STRING)
private Gender gender;
@Enumerated(EnumType.STRING)
private BloodGroup bloodGroup;
private String city;
@Column(unique = true, nullable = false)
private String aadharnumber;
private String password;
// Constructors, getters, setters
}
enum Gender { MALE, FEMALE, OTHER }
enum BloodGroup { A_POSITIVE, A_NEGATIVE, B_POSITIVE, B_NEGATIVE, AB_POSITIVE, AB_NEGATIVE, O_POSITIVE, O_NEGATIVE }
2. Donor Repository
@Repository
public interface DonorRepository extends JpaRepository<Donor, Long> {
Optional<Donor> findByEmail(String email);
boolean existsByEmail(String email);
boolean existsByMobile(String mobile);
boolean existsByAadharnumber(String aadharnumber);
@Query("SELECT d FROM Donor d WHERE " +
"(:gender IS NULL OR d.gender = :gender) AND " +
"(:city IS NULL OR LOWER(d.city) LIKE LOWER(CONCAT('%', :city, '%'))) AND " +
"(:bloodGroup IS NULL OR d.bloodGroup = :bloodGroup)")
List<Donor> findDonorsWithFilters(@Param("gender") Gender gender,
@Param("city") String city,
@Param("bloodGroup") BloodGroup bloodGroup);
}
3. Auth Controller
@RestController
@RequestMapping("/api/auth")
@CrossOrigin(origins = "*")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/register")
public ResponseEntity<?> registerDonor(@Valid @RequestBody DonorRegistrationDto registrationDto) {
try {
DonorResponseDto donor = authService.registerDonor(registrationDto);
return ResponseEntity.ok(new ApiResponse("Registration successful", donor));
} catch (RuntimeException e) {
return ResponseEntity.badRequest().body(new ApiResponse(e.getMessage(), null));
}
}
@PostMapping("/login")
public ResponseEntity<?> loginDonor(@Valid @RequestBody LoginDto loginDto) {
try {
DonorResponseDto donor = authService.loginDonor(loginDto);
return ResponseEntity.ok(new ApiResponse("Login successful", donor));
} catch (RuntimeException e) {
return ResponseEntity.badRequest().body(new ApiResponse(e.getMessage(), null));
}
}
}
4. Donor Controller
@RestController
@RequestMapping("/api/donors")
@CrossOrigin(origins = "*")
public class DonorController {
@Autowired
private DonorService donorService;
@GetMapping("/search")
public ResponseEntity<List<DonorResponseDto>> searchDonors(
@RequestParam(required = false) String gender,
@RequestParam(required = false) String city,
@RequestParam(required = false) String bloodGroup) {
List<DonorResponseDto> donors = donorService.searchDonors(gender, city, bloodGroup);
return ResponseEntity.ok(donors);
}
@GetMapping
public ResponseEntity<List<DonorResponseDto>> getAllDonors() {
List<DonorResponseDto> donors = donorService.getAllDonors();
return ResponseEntity.ok(donors);
}
}
5. Auth Service
@Service
public class AuthService {
@Autowired
private DonorRepository donorRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public DonorResponseDto registerDonor(DonorRegistrationDto registrationDto) {
// Validation checks
if (donorRepository.existsByEmail(registrationDto.getEmail())) {
throw new RuntimeException("Email already registered");
}
if (donorRepository.existsByMobile(registrationDto.getMobile())) {
throw new RuntimeException("Mobile number already registered");
}
if (donorRepository.existsByAadharnumber(registrationDto.getAadharnumber())) {
throw new RuntimeException("Aadhar number already registered");
}
Donor donor = new Donor();
donor.setName(registrationDto.getName());
donor.setEmail(registrationDto.getEmail());
donor.setMobile(registrationDto.getMobile());
donor.setGender(Gender.valueOf(registrationDto.getGender().toUpperCase()));
donor.setBloodGroup(BloodGroup.valueOf(registrationDto.getBloodGroup().toUpperCase()));
donor.setCity(registrationDto.getCity());
donor.setAadharnumber(registrationDto.getAadharnumber());
donor.setPassword(passwordEncoder.encode(registrationDto.getPassword()));
Donor savedDonor = donorRepository.save(donor);
return convertToResponseDto(savedDonor);
}
public DonorResponseDto loginDonor(LoginDto loginDto) {
Donor donor = donorRepository.findByEmail(loginDto.getEmail())
.orElseThrow(() -> new RuntimeException("Invalid email or password"));
if (!passwordEncoder.matches(loginDto.getPassword(), donor.getPassword())) {
throw new RuntimeException("Invalid email or password");
}
return convertToResponseDto(donor);
}
}
6. Application Properties
# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/blood_donor_db
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA Configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# Server Configuration
server.port=8080
7. Maven Dependencies (pom.xml)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
API Endpoints
- POST
/api/auth/register
- Register new donor - POST
/api/auth/login
- Login donor - GET
/api/donors/search?gender=MALE&city=Delhi&bloodGroup=O_POSITIVE
- Search donors with filters - GET
/api/donors
- Get all donors
Implementation Steps
- Setup: Create a new Spring Boot project with the above dependencies
- Database: Set up MySQL database and configure connection
- Entities: Create the Donor entity with proper validations
- Repository: Implement custom query methods for filtering
- Services: Add business logic for registration and search
- Controllers: Create REST endpoints
- Testing: Test all endpoints using Postman or similar tools
This Spring Boot application provides all the functionality you requested: donor registration with validation, login functionality, and a comprehensive search system that allows filtering by gender, city, blood group, and their combinations. The system prevents duplicate registrations and includes proper error handling.
please use spring boot and angular int his project
I understand you want to create a Blood Donor Search project using Spring Boot for the backend API and Angular for the frontend. Since v0 is optimized for React/Next.js applications, I'll provide you with a comprehensive guide for both the Spring Boot backend and Angular frontend that you can implement in your local development environment.
Project Architecture
blood-donor-project/
├── backend/ (Spring Boot)
│ ├── src/main/java/com/blooddonor/
│ └── pom.xml
└── frontend/ (Angular)
├── src/app/
├── package.json
└── angular.json
Spring Boot Backend Implementation
1. Project Structure
backend/
├── src/main/java/com/blooddonor/
│ ├── BloodDonorApplication.java
│ ├── config/
│ │ ├── CorsConfig.java
│ │ └── SecurityConfig.java
│ ├── controller/
│ │ ├── AuthController.java
│ │ └── DonorController.java
│ ├── dto/
│ │ ├── DonorRegistrationDto.java
│ │ ├── LoginDto.java
│ │ ├── DonorResponseDto.java
│ │ └── ApiResponse.java
│ ├── entity/
│ │ └── Donor.java
│ ├── repository/
│ │ └── DonorRepository.java
│ ├── service/
│ │ ├── DonorService.java
│ │ └── AuthService.java
│ └── enums/
│ ├── Gender.java
│ └── BloodGroup.java
2. Key Backend Files
Donor Entity:
@Entity
@Table(name = "donors")
public class Donor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
@NotBlank(message = "Name is required")
private String name;
@Column(unique = true, nullable = false)
@Email(message = "Invalid email format")
private String email;
@Column(unique = true, nullable = false)
@Pattern(regexp = "^[0-9]{10}$", message = "Mobile number must be 10 digits")
private String mobile;
@Enumerated(EnumType.STRING)
@NotNull(message = "Gender is required")
private Gender gender;
@Enumerated(EnumType.STRING)
@NotNull(message = "Blood group is required")
private BloodGroup bloodGroup;
@NotBlank(message = "City is required")
private String city;
@Column(unique = true, nullable = false)
@Pattern(regexp = "^[0-9]{12}$", message = "Aadhar number must be 12 digits")
private String aadharnumber;
@NotBlank(message = "Password is required")
private String password;
// Constructors, getters, setters
}
Auth Controller:
@RestController
@RequestMapping("/api/auth")
@CrossOrigin(origins = "http://localhost:4200")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/register")
public ResponseEntity<ApiResponse> registerDonor(@Valid @RequestBody DonorRegistrationDto registrationDto) {
try {
DonorResponseDto donor = authService.registerDonor(registrationDto);
return ResponseEntity.ok(new ApiResponse(true, "Registration successful", donor));
} catch (RuntimeException e) {
return ResponseEntity.badRequest().body(new ApiResponse(false, e.getMessage(), null));
}
}
@PostMapping("/login")
public ResponseEntity<ApiResponse> loginDonor(@Valid @RequestBody LoginDto loginDto) {
try {
DonorResponseDto donor = authService.loginDonor(loginDto);
return ResponseEntity.ok(new ApiResponse(true, "Login successful", donor));
} catch (RuntimeException e) {
return ResponseEntity.badRequest().body(new ApiResponse(false, e.getMessage(), null));
}
}
}
Donor Controller:
@RestController
@RequestMapping("/api/donors")
@CrossOrigin(origins = "http://localhost:4200")
public class DonorController {
@Autowired
private DonorService donorService;
@GetMapping("/search")
public ResponseEntity<ApiResponse> searchDonors(
@RequestParam(required = false) String gender,
@RequestParam(required = false) String city,
@RequestParam(required = false) String bloodGroup) {
List<DonorResponseDto> donors = donorService.searchDonors(gender, city, bloodGroup);
return ResponseEntity.ok(new ApiResponse(true, "Donors retrieved successfully", donors));
}
}
Angular Frontend Implementation
1. Project Setup Commands
ng new blood-donor-frontend
cd blood-donor-frontend
ng add @angular/material
npm install @angular/forms @angular/common/http
2. Angular Project Structure
src/app/
├── components/
│ ├── register/
│ │ ├── register.component.ts
│ │ ├── register.component.html
│ │ └── register.component.css
│ ├── login/
│ │ ├── login.component.ts
│ │ ├── login.component.html
│ │ └── login.component.css
│ ├── home/
│ │ ├── home.component.ts
│ │ ├── home.component.html
│ │ └── home.component.css
│ └── donor-card/
│ ├── donor-card.component.ts
│ ├── donor-card.component.html
│ └── donor-card.component.css
├── services/
│ ├── auth.service.ts
│ └── donor.service.ts
├── models/
│ ├── donor.model.ts
│ └── api-response.model.ts
├── guards/
│ └── auth.guard.ts
└── app-routing.module.ts
3. Key Angular Files
Donor Model:
export interface Donor {
id?: number;
name: string;
email: string;
mobile: string;
gender: 'MALE' | 'FEMALE' | 'OTHER';
bloodGroup: 'A_POSITIVE' | 'A_NEGATIVE' | 'B_POSITIVE' | 'B_NEGATIVE' | 'AB_POSITIVE' | 'AB_NEGATIVE' | 'O_POSITIVE' | 'O_NEGATIVE';
city: string;
aadharnumber: string;
password?: string;
}
export interface ApiResponse {
success: boolean;
message: string;
data: any;
}
Auth Service:
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = 'http://localhost:8080/api/auth';
constructor(private http: HttpClient) {}
register(donor: Donor): Observable<ApiResponse> {
return this.http.post<ApiResponse>(`${this.apiUrl}/register`, donor);
}
login(credentials: {email: string, password: string}): Observable<ApiResponse> {
return this.http.post<ApiResponse>(`${this.apiUrl}/login`, credentials);
}
logout(): void {
localStorage.removeItem('currentUser');
}
getCurrentUser(): Donor | null {
const user = localStorage.getItem('currentUser');
return user ? JSON.parse(user) : null;
}
isLoggedIn(): boolean {
return !!this.getCurrentUser();
}
}
Register Component:
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent {
registerForm: FormGroup;
bloodGroups = ['A_POSITIVE', 'A_NEGATIVE', 'B_POSITIVE', 'B_NEGATIVE', 'AB_POSITIVE', 'AB_NEGATIVE', 'O_POSITIVE', 'O_NEGATIVE'];
genders = ['MALE', 'FEMALE', 'OTHER'];
constructor(
private fb: FormBuilder,
private authService: AuthService,
private router: Router,
private snackBar: MatSnackBar
) {
this.registerForm = this.fb.group({
name: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email]],
mobile: ['', [Validators.required, Validators.pattern('^[0-9]{10}$')]],
gender: ['', Validators.required],
bloodGroup: ['', Validators.required],
city: ['', Validators.required],
aadharnumber: ['', [Validators.required, Validators.pattern('^[0-9]{12}$')]],
password: ['', [Validators.required, Validators.minLength(6)]]
});
}
onSubmit(): void {
if (this.registerForm.valid) {
this.authService.register(this.registerForm.value).subscribe({
next: (response) => {
this.snackBar.open('Registration successful!', 'Close', { duration: 3000 });
this.router.navigate(['/login']);
},
error: (error) => {
this.snackBar.open(error.error.message || 'Registration failed', 'Close', { duration: 3000 });
}
});
}
}
}
Home Component (Search):
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
donors: Donor[] = [];
searchForm: FormGroup;
bloodGroups = ['A_POSITIVE', 'A_NEGATIVE', 'B_POSITIVE', 'B_NEGATIVE', 'AB_POSITIVE', 'AB_NEGATIVE', 'O_POSITIVE', 'O_NEGATIVE'];
genders = ['MALE', 'FEMALE', 'OTHER'];
constructor(
private fb: FormBuilder,
private donorService: DonorService
) {
this.searchForm = this.fb.group({
gender: [''],
city: [''],
bloodGroup: ['']
});
}
ngOnInit(): void {
this.searchDonors();
}
searchDonors(): void {
const filters = this.searchForm.value;
this.donorService.searchDonors(filters).subscribe({
next: (response) => {
this.donors = response.data;
},
error: (error) => {
console.error('Search failed:', error);
}
});
}
clearFilters(): void {
this.searchForm.reset();
this.searchDonors();
}
}
Home Component Template:
<div class="container">
<h2>Blood Donor Search</h2>
<mat-card class="search-card">
<mat-card-header>
<mat-card-title>Search Filters</mat-card-title>
</mat-card-header>
<mat-card-content>
<form [formGroup]="searchForm" (ngSubmit)="searchDonors()">
<div class="filter-row">
<mat-form-field>
<mat-label>Gender</mat-label>
<mat-select formControlName="gender">
<mat-option value="">All</mat-option>
<mat-option *ngFor="let gender of genders" [value]="gender">
{{gender}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-label>City</mat-label>
<input matInput formControlName="city" placeholder="Enter city">
</mat-form-field>
<mat-form-field>
<mat-label>Blood Group</mat-label>
<mat-select formControlName="bloodGroup">
<mat-option value="">All</mat-option>
<mat-option *ngFor="let bg of bloodGroups" [value]="bg">
{{bg.replace('_', ' ')}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="button-row">
<button mat-raised-button color="primary" type="submit">Search</button>
<button mat-button type="button" (click)="clearFilters()">Clear</button>
</div>
</form>
</mat-card-content>
</mat-card>
<div class="donors-grid">
<app-donor-card *ngFor="let donor of donors" [donor]="donor"></app-donor-card>
</div>
</div>
Setup Instructions
Backend Setup:
- Create Spring Boot project with dependencies: Web, JPA, MySQL, Validation, Security
- Configure
application.properties
with database settings - Run:
mvn spring-boot:run
(Backend runs on port 8080)
Frontend Setup:
- Install Angular CLI:
npm install -g @angular/cli
- Create project:
ng new blood-donor-frontend
- Install Angular Material:
ng add @angular/material
- Run:
ng serve
(Frontend runs on port 4200)
This full-stack application provides donor registration with validation, login functionality, and a comprehensive search system with filtering by gender, city, blood group, and their combinations. The Angular frontend communicates with the Spring Boot backend via REST APIs, creating a complete blood donor search platform.
make the project