Jak zmienić pole formularza z id na wartość tekstową?

Jak zmienić pole formularza z id na wartość tekstową?
MJ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Witam

mam problem z tym że mój select wg. mnie przyjmuje złą wartość, ale do rzeczy, poniżej kod:

SPRING:

Model danych i DTO

Kopiuj
@Entity
@Getter
@Setter
public class Offer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "user_id")
    private UserEmployee user;
    @ManyToOne
    @JoinColumn(name = "client_id")
    private Client client;
    @ManyToOne
    private Property property;
    private Boolean isBooked;
    private Boolean isAvailable;
}
Kopiuj
@Getter
@Setter
public class OfferDto {
    private Long id;
    @NotNull(message = "You have to choose employee")
    private Long userId;
    @NotNull(message = "You have to choose client")
    private Long clientId;
    @NotNull(message = "You have to choose property")
    private Long propertyId;
    private Long reservationId;
    private Boolean isBooked;
    private Boolean isAvailable;
}

MAPPER I SERWIS

Kopiuj
@Service
@RequiredArgsConstructor
public class OfferMapper {

    private final PropertyRepository propertyRepository;
    private final UserRepository userRepository;
    private final ClientRepository clientRepository;


    public OfferDto map(Offer offer) {
        OfferDto dto = new OfferDto();
        dto.setId(offer.getId());
        dto.setPropertyId(offer.getProperty().getId());
        dto.setClientId(offer.getClient().getId());
        dto.setUserId(offer.getUser().getId());
        dto.setIsBooked(offer.getIsBooked());
        dto.setIsAvailable(offer.getIsAvailable());

        return dto;
    }

    public Offer map(OfferDto dto) {
        Offer offer = new Offer();
        offer.setId(dto.getId());
        Property property = propertyRepository.findById(dto.getPropertyId()).orElseThrow(() -> new ResourceNotFoundException("Property not found"));
        offer.setProperty(property);
        Client client = clientRepository.findById(dto.getClientId()).orElseThrow(() -> new ResourceNotFoundException("Client not found"));
        offer.setClient(client);
        UserEmployee userEmployee = userRepository.findById(dto.getUserId()).orElseThrow(() -> new ResourceNotFoundException("Employee not found"));
        offer.setUser(userEmployee);
        offer.setIsBooked(dto.getIsBooked());
        offer.setIsAvailable(dto.getIsAvailable());

        return offer;
    }

}
Kopiuj
@Service
@RequiredArgsConstructor
public class OfferService {

    private final OffersRepository offersRepository;
    private final UserRepository userRepository;
    private  final PropertyRepository propertyRepository;
    private final ClientRepository clientRepository;
    private final OfferMapper offerMapper;
    private final ValidationService validationService;


    @Transactional
    public OfferDto saveOffer(@Valid OfferDto offerDto){
        Offer offer = offerMapper.map(offerDto);
        validationService.validateData(offer);
        offer.setIsAvailable(true);
        Offer saved = offersRepository.save(offer);
        return offerMapper.map(saved);
    }
    }
Kopiuj
@RestController
@RequestMapping("/api/offers")
@CrossOrigin("*")
@RequiredArgsConstructor
public class OfferController {

    private final OfferService offerService;


    @PostMapping
    public ResponseEntity<OfferDto> saveOffer(@RequestBody @Valid OfferDto offerDto) {
        OfferDto saved = offerService.saveOffer(offerDto);
        URI uri = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(saved.getId())
                .toUri();
        return ResponseEntity.created(uri).body(saved);
    }
    }

Jeżeli chodzi o serwis i kontroler to wrzucam tylko metode odpowiedzialną za dodawanie oferty bo w tym jest kłopot.

KOD REACTA:

Kopiuj
import axios from "axios";

class OffersService {
	static BASE_URL = "http://localhost:8080/api/offers";

	static async addOffer (offerData, token){
		try{
			const response = await axios.post(`${OffersService.BASE_URL}`, offerData, 
				{
					headers: {Authorization: `Bearer ${token}`}
				}
			)
			return response.data;
		}catch(error){
			if(error.response && error.response.data){
                throw error.response.data
            }else{
                throw new Error("Adding the offer failed. Please try again")
            }
		}
	}
    }

KOMPONENT:

Kopiuj
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import OffersService from "../../service/OffersService";
import Notification, { showNotification } from "../alerts/Notification";
import ClientService from "../../service/ClientService";
import PropertyService from "../../service/PropertyService";
import EmployeeService from '../../service/EmployeeService'

function AddOffer() {
	const [offerData, setOfferData] = useState({
		userId: "",
		clientId: "",
		propertyId: "",
		isBooked: "",
		isAvailable: "",
	});

	const [errors, setErrors] = useState({
		userId: "",
		clientId: "",
		propertyId: "",
	});

	const [clients, setClients] = useState([]);
	const [properties, setProperties] = useState([]);
	const [employees, setEmployees] = useState([]);

	useEffect(() => {
		fetchClients();
		fetchProperties();
		fetchEmployees();
	}, []);

	const fetchClients = async () => {
		try {
			const token = localStorage.getItem("accessToken");
			const response = await ClientService.getAllClients(token); 
			setClients(response.data);
		} catch (error) {
			console.log(error);
		}
	};

	const fetchProperties = async () => {
		try {
			const token = localStorage.getItem("accessToken");
			const response = await PropertyService.getAllProperties(token); 
			setProperties(response.data);
		} catch (error) {
			console.log(error);
		}
	};

	const fetchEmployees = async () => {
		try {
			const token = localStorage.getItem("accessToken");
			const response = await EmployeeService.getAllEmployees(token); 
			setEmployees(response.data);
		} catch (error) {
			console.log(error);
		}
	};

	const navi = useNavigate();

	const handleInputChange = (e) => {
		const { name, value } = e.target;
		setOfferData({ ...offerData, [name]: value });
		console.log(value);
		setErrors({ ...errors, [name]: "" });
	};

	const handleCheckboxChange = (e) => {
		const { name, checked } = e.target;
		setOfferData({ ...offerData, [name]: checked });
	};

	const handleSubmit = async (e) => {
		e.preventDefault();
		try {
			const token = localStorage.getItem("accessToken");
			await OffersService.addOffer(offerData, token);
			setErrors({});
			showNotification("Offer added successfully", "success");
			navi("/offers");
		} catch (error) {
			if (error instanceof Object) {
				setErrors(error);
			} else {
				console.log(error);
			}
		}
	};

	return (
		<div className="main-content">
			<div className="main-content-post">
				<h2>Add offer</h2>
				{errors.general && <p className="error-msg">{errors.general}</p>}
				<form onSubmit={handleSubmit} className="post-form">
					<div className="apartment-post-box">
						<div className="first-input-box-post">
							<div className="input-box-post">
								<label htmlFor="">User:</label>
								<select
								name="userId"
								className="select"
								value={offerData.userId}
								onChange={handleInputChange}
								>
									<option value="">Select Employee</option>
									{employees.map((empl) => (
										<option key={empl.id} value={empl.id}>
											{empl.firstName}
										</option>
									))}
								</select>
							</div>
							{errors.userId && <p className="error-msg">{errors.userId}</p>}

							<div className="input-box-post">
								<label htmlFor="clientId">Client:</label>
								<select
									name="clientId"
									className="select"
									value={offerData.clientId}
									onChange={handleInputChange}
								>
									<option value="clientId">Select Client</option>
									{clients.map((client) => (
										<option key={client.id} value={client.id}>
											{client.firstName} {client.lastName}
										</option>
									))}
								</select>
							</div>
							{errors.clientId && (
								<p className="error-msg">{errors.clientId}</p>
							)}
							<div className="input-box-post">
								<label htmlFor="">Property:</label>
								<select
								name="propertyId"
								className="select"
								value={offerData.propertyId}
								onChange={handleInputChange}
								>
									<option value="propertyId">Select Property</option>
									{properties.map((property) => (
										<option key={property.id} value={property.id}>
											{property.address}, {property.price} EUR
										</option>
									))}

								</select>
							</div>
							{errors.propertyId && (
								<p className="error-msg">{errors.propertyId}</p>
							)}
						</div>
						<div className="second-input-box-post">
							<div className="input-checkbox-group">
								<div className="input-box-post">
									<label htmlFor="duplex">Booked:</label>
									<input
										type="checkbox"
										id="isBooked"
										name="isBooked"
										checked={offerData.isBooked}
										onChange={handleCheckboxChange}
									/>
								</div>

								<div className="input-box-post">
									<label htmlFor="duplex">Available:</label>
									<input
										type="checkbox"
										id="isAvailable"
										name="isAvailable"
										checked={offerData.isAvailable}
										onChange={handleCheckboxChange}
										disabled
									/>
								</div>
							</div>
						</div>
					</div>

					<button type="submit" className="my-btn">
						Add
					</button>
				</form>
			</div>
		</div>
	);
}

export default AddOffer;

Sytuacja wygląda tak, gdy miałem ten sam komponent ale ze zwykłymi inputami zamiast selectów i tam wpisywałem np, ID użytkownika ręcznie to wszystko było ok, ale było to mało 'przyjazne', wiec dorzuciłem selecty aby osoba która korzysta sama mógła wybrać spośród dostępnych pracowników czy nieruchomości.
Select jako value przyjmuje offerData.userId, a jednak w konsoli widze ze jest to wartość imienia i nazwiska pracownika jakiego wybrałem. Dlaczego tak się dzieje?
Dostaje przez to błąd po stronie serwera:

Kopiuj
2024-05-20T16:37:51.366+02:00  WARN 14976 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.lang.Long` from String "John": not a valid `java.lang.Long` value]

Z oczywistych względów bo Spring oczekuje ID a nie imienia i nazwiska.

BB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 68
0

Skoro tak to prawdopodobnie z usera nie dostaje id tylko inne dane ,i chyba tam szukaj problemu.

MJ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

No tak, to wiem, ale dlaczego skoro value jest ustawione tak że teoretycznie powinno pobierac jego ID

RequiredNickname
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 652
1

Konia z rzędem temu komu się będzie chciało przekopywać przez cały ten kod ;)

Odpal sobie debbuger zarówno na endpoincie z którego pobierasz dane jak i na froncie i posprawdzaj co tam siedzi i przejdź po sznurku do kłębka.

I poczytaj czym są konstruktory w javie ;-)

MJ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0
RequiredNickname napisał(a):

Konia z rzędem temu komu się będzie chciało przekopywać przez cały ten kod ;)

Odpal sobie debbuger zarówno na endpoincie z którego pobierasz dane jak i na froncie i posprawdzaj co tam siedzi i przejdź po sznurku do kłębka.

I poczytaj czym są konstruktory w javie ;-)

Tak zrobie szefie, tylko co ma konstruktor w javie teraz do tego?

Black007
  • Rejestracja: dni
  • Ostatnio: dni
0

Mógłbyś dorzucić dłuższy log?
Kiedyś programowałem w reakcie. Pierwsze co, to F12 network, żeby zobaczyć co wysyłam do backendu.
Z tego co widzę to idzie post z Body Offer, czy coś przegapiłem?

MJ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Ogarnięte, do zamknięcia.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.