From 992f1cd0bac99b878b6e6f963c85470187a3c99a Mon Sep 17 00:00:00 2001 From: Mauran Date: Thu, 8 Feb 2024 16:27:20 +0100 Subject: [PATCH 1/3] feat(backend): show all job offers if there is no recommendation Signed-off-by: Mauran --- .../backend/service/JobOfferService.kt | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt b/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt index 21a9593..a890e1e 100644 --- a/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt +++ b/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt @@ -43,22 +43,42 @@ class JobOfferService( recommendation.id // Assuming Recommendation has an 'id' field representing its ID } - val requestJobOffers = RequestResponseFactory.newRequest(requestId) - .setGetMultipleJobOffersRequest( - Jobs.GetMultipleJobOffersRequest.newBuilder() - .addAllIds(recommendationIds) - ).build() - - val responseJobOffers = natsService.requestWithReply(findMultipleSubject, requestJobOffers) - - // Handle the response - if (!responseJobOffers.hasGetMultipleJobOffersResponse()) { - throw Exception("Invalid response") - } - - val getUserJobOffersResponse = responseJobOffers.getMultipleJobOffersResponse - return getUserJobOffersResponse.jobOffersList.map { jobOffer -> - convertJobOfferFromProto(jobOffer) + if (recommendationIds.size === 0) { + val requestJobOffers = RequestResponseFactory.newRequest(requestId) + .setGetUserJobOffersRequest( + Jobs.GetUserJobOffersRequest.newBuilder() + .setUserId(userId) + ).build() + + val responseJobOffers = natsService.requestWithReply(findAllSubject, requestJobOffers) + + // Handle the response + if (!responseJobOffers.hasGetUserJobOffersResponse()) { + throw Exception("Invalid response") + } + + val getUserJobOffersResponse = responseJobOffers.getUserJobOffersResponse + return getUserJobOffersResponse.jobOffersList.map { jobOffer -> + convertJobOfferFromProto(jobOffer) + } + }else{ + val requestJobOffers = RequestResponseFactory.newRequest(requestId) + .setGetMultipleJobOffersRequest( + Jobs.GetMultipleJobOffersRequest.newBuilder() + .addAllIds(recommendationIds) + ).build() + + val responseJobOffers = natsService.requestWithReply(findMultipleSubject, requestJobOffers) + + // Handle the response + if (!responseJobOffers.hasGetMultipleJobOffersResponse()) { + throw Exception("Invalid response") + } + + val getUserJobOffersResponse = responseJobOffers.getMultipleJobOffersResponse + return getUserJobOffersResponse.jobOffersList.map { jobOffer -> + convertJobOfferFromProto(jobOffer) + } } } From 38a14c51362814cb2457b4a18c4784ede3492413 Mon Sep 17 00:00:00 2001 From: Mauran Date: Thu, 8 Feb 2024 17:52:20 +0100 Subject: [PATCH 2/3] feat: get job applications in back and front Signed-off-by: Mauran --- .../backend/controller/JobOffersController.kt | 11 ++- .../backend/service/JobOfferService.kt | 26 ++++++- .../src/main/resources/application.yml | 1 + .../jobOffers/GetJobOffersAppliedForUser.kt | 46 +++++++++++ .../jobs/repository/JobOfferRepository.kt | 24 ++++++ .../linkedout/jobs/service/JobOfferService.kt | 4 + .../src/main/resources/application.properties | 12 ++- .../function/profile/SetProfileOfUser.kt | 2 + backend/protobuf/src/main/proto/request.proto | 1 + .../protobuf/src/main/proto/response.proto | 1 + .../src/main/proto/services/jobs.proto | 9 +++ front/assets/translations/en_US.json | 3 + front/assets/translations/fr_FR.json | 3 + front/src/pages/MainTabNav.tsx | 5 +- .../pages/jobOffer/JobOfferApplicationNav.tsx | 46 +++++++++++ front/src/pages/jobOffer/JobOfferNav.tsx | 1 + .../jobOffer/jobOfferApplicationPage.tsx | 77 +++++++++++++++++++ front/src/pages/login/FirstLoginPage.tsx | 1 - front/src/store/api/jobOfferApiSlice.ts | 16 ++++ 19 files changed, 282 insertions(+), 7 deletions(-) create mode 100644 backend/jobs/src/main/kotlin/com/linkedout/jobs/function/jobOffers/GetJobOffersAppliedForUser.kt create mode 100644 front/src/pages/jobOffer/JobOfferApplicationNav.tsx create mode 100644 front/src/pages/jobOffer/jobOfferApplicationPage.tsx diff --git a/backend/api_gateway/src/main/kotlin/com/linkedout/backend/controller/JobOffersController.kt b/backend/api_gateway/src/main/kotlin/com/linkedout/backend/controller/JobOffersController.kt index 3dbe51c..0535af5 100644 --- a/backend/api_gateway/src/main/kotlin/com/linkedout/backend/controller/JobOffersController.kt +++ b/backend/api_gateway/src/main/kotlin/com/linkedout/backend/controller/JobOffersController.kt @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -15,8 +16,16 @@ import java.security.Principal @RestController @RequestMapping("/api/v1/jobOffers") class JobOffersController(private val jobOffersService: JobOfferService) { + @GetMapping - open fun getJobOffers(request: ServerHttpRequest, principal: Principal): Flux { + open fun getJobOffers( + request: ServerHttpRequest, + principal: Principal, + @RequestParam(required = false, defaultValue = "false") onlyApplied: Boolean + ): Flux { + if (onlyApplied) { + return Flux.fromIterable(jobOffersService.findAllApplied(request.id, principal.name)) + } return Flux.fromIterable(jobOffersService.findAll(request.id, principal.name)) } diff --git a/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt b/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt index a890e1e..77f842c 100644 --- a/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt +++ b/backend/api_gateway/src/main/kotlin/com/linkedout/backend/service/JobOfferService.kt @@ -17,6 +17,7 @@ import java.time.LocalDate class JobOfferService( private val natsService: NatsService, @Value("\${app.services.jobOffers.subjects.findAllForUser}") private val findAllSubject: String, + @Value("\${app.services.jobOffers.subjects.findAllAppliedForUser}") private val findAllAppliedSubject: String, @Value("\${app.services.jobOffers.subjects.findOneForUser}") private val findOneSubject: String, @Value("\${app.services.jobOffers.subjects.findMultiple}") private val findMultipleSubject: String, @Value("\${app.services.jobOffers.subjects.applyTo}") private val applyToSubject: String, @@ -24,7 +25,7 @@ class JobOfferService( ) { fun findAll(requestId: String, userId: String): List { - // Request job offers from the job service + // Request job offers from the recommendation val request = RequestResponseFactory.newRequest(requestId) .setGetRecommendationRequest( Recommendations.GetRecommendationRequest.newBuilder() @@ -61,7 +62,7 @@ class JobOfferService( return getUserJobOffersResponse.jobOffersList.map { jobOffer -> convertJobOfferFromProto(jobOffer) } - }else{ + } else { val requestJobOffers = RequestResponseFactory.newRequest(requestId) .setGetMultipleJobOffersRequest( Jobs.GetMultipleJobOffersRequest.newBuilder() @@ -82,6 +83,27 @@ class JobOfferService( } } + fun findAllApplied(requestId: String, userId: String): List { + // Request job offers from the job service + val requestJobOffers = RequestResponseFactory.newRequest(requestId) + .setGetUserJobOffersAppliedRequest( + Jobs.GetUserJobOffersAppliedRequest.newBuilder() + .setUserId(userId) + ).build() + + val responseJobOffers = natsService.requestWithReply(findAllAppliedSubject, requestJobOffers) + + // Handle the response + if (!responseJobOffers.hasGetUserJobOffersAppliedResponse()) { + throw Exception("Invalid response") + } + + val getUserJobOffersAppliedResponse = responseJobOffers.getUserJobOffersAppliedResponse + return getUserJobOffersAppliedResponse.jobOffersList.map { jobOffer -> + convertJobOfferFromProto(jobOffer) + } + } + fun findOne(requestId: String, userId: String, jobOfferId: String): JobOffer { // Request the job offer from the job offer service val request = RequestResponseFactory.newRequest(requestId) diff --git a/backend/api_gateway/src/main/resources/application.yml b/backend/api_gateway/src/main/resources/application.yml index 31b0b95..84bcc01 100644 --- a/backend/api_gateway/src/main/resources/application.yml +++ b/backend/api_gateway/src/main/resources/application.yml @@ -28,6 +28,7 @@ app: jobOffers: subjects: findAllForUser: jobs.findAllJobOffersForUser + findAllAppliedForUser: jobs.findAllJobOffersAppliedForUser findMultiple: jobs.findMultipleJobOffers findOneForUser: jobs.findOneJobOfferForUser applyTo: jobs.applyToJobOffer diff --git a/backend/jobs/src/main/kotlin/com/linkedout/jobs/function/jobOffers/GetJobOffersAppliedForUser.kt b/backend/jobs/src/main/kotlin/com/linkedout/jobs/function/jobOffers/GetJobOffersAppliedForUser.kt new file mode 100644 index 0000000..25a1734 --- /dev/null +++ b/backend/jobs/src/main/kotlin/com/linkedout/jobs/function/jobOffers/GetJobOffersAppliedForUser.kt @@ -0,0 +1,46 @@ +package com.linkedout.jobs.function.jobOffers + +import com.linkedout.common.utils.RequestResponseFactory +import com.linkedout.common.utils.handleRequestError +import com.linkedout.jobs.converter.jobOffers.JobOfferWithJobAndCompanyToProto +import com.linkedout.jobs.service.JobOfferService +import com.linkedout.proto.RequestOuterClass.Request +import com.linkedout.proto.ResponseOuterClass.Response +import com.linkedout.proto.services.Jobs +import org.springframework.stereotype.Component +import java.util.UUID +import java.util.function.Function + +@Component +class GetJobOffersAppliedForUser(private val jobOfferService: JobOfferService) : Function { + override fun apply(t: Request): Response = handleRequestError { + // Extract the request + val request = t.getUserJobOffersAppliedRequest + val userId = UUID.fromString(request.userId) + + // Get all the job offers from the database + val reactiveResponse = jobOfferService.findAllAppliedForUser(userId) + .map { jobOffer -> + JobOfferWithJobAndCompanyToProto().convert(jobOffer) + .setStatusValue(jobOffer.jobApplicationStatus) + } + .filter { it != null } + .reduce(Jobs.GetUserJobOffersAppliedResponse.newBuilder()) { builder, jobOffer -> + builder.addJobOffers(jobOffer) + builder + } + .map { builder -> + builder.build() + } + + // Block until the response is ready + val response = reactiveResponse.block() + ?: return RequestResponseFactory.newSuccessfulResponse() + .setGetUserJobOffersAppliedResponse(Jobs.GetUserJobOffersAppliedResponse.getDefaultInstance()) + .build() + + return RequestResponseFactory.newSuccessfulResponse() + .setGetUserJobOffersAppliedResponse(response) + .build() + } +} diff --git a/backend/jobs/src/main/kotlin/com/linkedout/jobs/repository/JobOfferRepository.kt b/backend/jobs/src/main/kotlin/com/linkedout/jobs/repository/JobOfferRepository.kt index 812bb5a..c256d68 100644 --- a/backend/jobs/src/main/kotlin/com/linkedout/jobs/repository/JobOfferRepository.kt +++ b/backend/jobs/src/main/kotlin/com/linkedout/jobs/repository/JobOfferRepository.kt @@ -32,6 +32,30 @@ interface JobOfferRepository : ReactiveCrudRepository { ) fun findAllForUserWithJobAndCompany(userId: UUID): Flux + @Query( + """ + SELECT jo.id as jobOfferId, + jo.job as jobId, + jo.title as jobOfferTitle, + jo.description as jobOfferDescription, + jo.geographicArea as jobOfferGeographicArea, + jo.startdate as jobOfferStartDate, + jo.enddate as jobOfferEndDate, + jo.company as companyId, + c.name as companyName, + jo.salary as jobOfferSalary, + jc.title as jobCategoryTitle, + j.title as jobTitle, + COALESCE(ja.status, -1) as jobApplicationStatus + FROM jobOffer jo + JOIN company c ON jo.company = c.id + JOIN job j ON jo.job = j.id + JOIN jobcategory jc ON j.category = jc.id + RIGHT JOIN jobapplication ja ON jo.id = ja.offerid AND ja.userid = :userId + """ + ) + fun findAllAppliedForUserWithJobAndCompany(userId: UUID): Flux + @Query( """ SELECT jo.id as jobOfferId, diff --git a/backend/jobs/src/main/kotlin/com/linkedout/jobs/service/JobOfferService.kt b/backend/jobs/src/main/kotlin/com/linkedout/jobs/service/JobOfferService.kt index e9a2684..9593ac5 100644 --- a/backend/jobs/src/main/kotlin/com/linkedout/jobs/service/JobOfferService.kt +++ b/backend/jobs/src/main/kotlin/com/linkedout/jobs/service/JobOfferService.kt @@ -15,6 +15,10 @@ class JobOfferService( return jobOffer.findAllForUserWithJobAndCompany(userId) } + fun findAllAppliedForUser(userId: UUID): Flux { + return jobOffer.findAllAppliedForUserWithJobAndCompany(userId) + } + fun findOneForUser(userId: UUID, jobOfferId: UUID): Mono { return jobOffer.findOneForUserWithJobAndCompany(userId, jobOfferId) } diff --git a/backend/jobs/src/main/resources/application.properties b/backend/jobs/src/main/resources/application.properties index a64e281..e11c5be 100644 --- a/backend/jobs/src/main/resources/application.properties +++ b/backend/jobs/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.cloud.function.definition=getJobs;getJob;getMultipleJobs;getJobCategories;getJobCategory;getMultipleJobCategories;getCompanies;getCompany;getMultipleCompanies;ensureCompanyExists;getJobOffersForUser;getJobOfferForUser;applyToJobOffer;getMultipleJobOffers +spring.cloud.function.definition=getJobs;getJob;getMultipleJobs;getJobCategories;getJobCategory;getMultipleJobCategories;getCompanies;getCompany;getMultipleCompanies;ensureCompanyExists;getJobOffersForUser;getJobOfferForUser;applyToJobOffer;getMultipleJobOffers;getJobOffersAppliedForUser spring.cloud.stream.bindings.getJobs-in-0.destination=jobs.findAll spring.cloud.stream.bindings.getJobs-in-0.group=jobsSvc @@ -125,4 +125,14 @@ spring.cloud.stream.bindings.getMultipleJobOffers-out-0.destination= spring.cloud.stream.bindings.getMultipleJobOffers-out-0.group=jobsSvc spring.cloud.stream.bindings.getMultipleJobOffers-out-0.binder=nats spring.cloud.stream.bindings.getMultipleJobOffers-out-0.content-type=application/vnd.linkedout.proto-response + +spring.cloud.stream.bindings.getJobOffersAppliedForUser-in-0.destination=jobs.findAllJobOffersAppliedForUser +spring.cloud.stream.bindings.getJobOffersAppliedForUser-in-0.group=jobsSvc +spring.cloud.stream.bindings.getJobOffersAppliedForUser-in-0.binder=nats +spring.cloud.stream.bindings.getJobOffersAppliedForUser-in-0.content-type=application/vnd.linkedout.proto-request +spring.cloud.stream.bindings.getJobOffersAppliedForUser-out-0.destination= +spring.cloud.stream.bindings.getJobOffersAppliedForUser-out-0.group=jobsSvc +spring.cloud.stream.bindings.getJobOffersAppliedForUser-out-0.binder=nats +spring.cloud.stream.bindings.getJobOffersAppliedForUser-out-0.content-type=application/vnd.linkedout.proto-response + nats.spring.server=nats://localhost:4222 diff --git a/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt b/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt index 94fed8c..7167938 100644 --- a/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt +++ b/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt @@ -1,3 +1,4 @@ + package com.linkedout.profile.function.profile import com.linkedout.common.utils.RequestResponseFactory @@ -15,6 +16,7 @@ import java.util.function.Function @Component class SetProfileOfUser(private val profileService: ProfileService) : Function { override fun apply(t: Request): Response = handleRequestError { + // Extract the request val request = t.setUserProfileRequest val userId = UUID.fromString(request.userId) diff --git a/backend/protobuf/src/main/proto/request.proto b/backend/protobuf/src/main/proto/request.proto index be3dda1..356b3e5 100644 --- a/backend/protobuf/src/main/proto/request.proto +++ b/backend/protobuf/src/main/proto/request.proto @@ -72,5 +72,6 @@ message Request { services.CreateRecommendationProfileRequest create_recommendation_profile_request = 58; services.CreateRecommendationExperienceRequest create_recommendation_experience_request = 59; services.GetMultipleJobOffersRequest get_multiple_job_offers_request = 60; + services.GetUserJobOffersAppliedRequest get_user_job_offers_applied_request = 61; } } diff --git a/backend/protobuf/src/main/proto/response.proto b/backend/protobuf/src/main/proto/response.proto index 686c856..3f5a703 100644 --- a/backend/protobuf/src/main/proto/response.proto +++ b/backend/protobuf/src/main/proto/response.proto @@ -76,5 +76,6 @@ message Response { services.CreateRecommendationProfileResponse create_recommendation_profile_response = 57; services.CreateRecommendationExperienceResponse create_recommendation_experience_response = 58; services.GetMultipleJobOffersResponse get_multiple_job_offers_response = 59; + services.GetUserJobOffersAppliedResponse get_user_job_offers_applied_response = 60; } } diff --git a/backend/protobuf/src/main/proto/services/jobs.proto b/backend/protobuf/src/main/proto/services/jobs.proto index c770c20..29fec1f 100644 --- a/backend/protobuf/src/main/proto/services/jobs.proto +++ b/backend/protobuf/src/main/proto/services/jobs.proto @@ -81,6 +81,15 @@ message GetUserJobOffersResponse { repeated models.JobOffer jobOffers = 1; } +// Get job offers that a user applied to +message GetUserJobOffersAppliedRequest { + string user_id = 1; +} + +message GetUserJobOffersAppliedResponse { + repeated models.JobOffer jobOffers = 1; +} + // Get a job offer for a user message GetUserJobOfferRequest { string user_id = 1; diff --git a/front/assets/translations/en_US.json b/front/assets/translations/en_US.json index d244f4a..9f826c9 100644 --- a/front/assets/translations/en_US.json +++ b/front/assets/translations/en_US.json @@ -25,6 +25,9 @@ "apply": "Apply", "applyTitle": "Apply confirmation", "applyConfirm": "Do you want to apply to this job?" + }, + "applied": { + "jobOfferAppliedList": "Job offer applied list" } }, "messaging": { diff --git a/front/assets/translations/fr_FR.json b/front/assets/translations/fr_FR.json index 716d2d4..bf705b6 100644 --- a/front/assets/translations/fr_FR.json +++ b/front/assets/translations/fr_FR.json @@ -25,6 +25,9 @@ "apply": "Postuler", "applyTitle": "Confirmation de candidature", "applyConfirm": "Voulez-vous candidater à cette offre ?" + }, + "applied": { + "jobOfferAppliedList": "Liste des offres d'emploi candidatés" } }, "messaging": { diff --git a/front/src/pages/MainTabNav.tsx b/front/src/pages/MainTabNav.tsx index 1254ac1..3024cc2 100644 --- a/front/src/pages/MainTabNav.tsx +++ b/front/src/pages/MainTabNav.tsx @@ -1,12 +1,13 @@ import { createMaterialBottomTabNavigator } from 'react-native-paper/react-navigation'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; -import InternalPagesNav from '@/pages/internal/InternalPagesNav'; import JobOffersNav from '@/pages/jobOffer/JobOfferNav'; import MessagingNav from '@/pages/messaging/MessagingNav'; import ProfileNav from '@/pages/profile/ProfileNav'; import i18n from '@/utils/i18n'; +import JobOffersApplicationNav from './jobOffer/JobOfferApplicationNav'; + /** * The parameter list for the MainTab navigator. */ @@ -43,7 +44,7 @@ const MainTabNav = () => { /> ( diff --git a/front/src/pages/jobOffer/JobOfferApplicationNav.tsx b/front/src/pages/jobOffer/JobOfferApplicationNav.tsx new file mode 100644 index 0000000..b7b3411 --- /dev/null +++ b/front/src/pages/jobOffer/JobOfferApplicationNav.tsx @@ -0,0 +1,46 @@ +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +import PaperNavigationBar from '@/components/utils/PaperNavigationBar'; +import i18n from '@/utils/i18n'; + +import JobOfferPage, { JobOfferPageParams } from './JobOfferPage'; +import JobOfferApplicationPage from './jobOfferApplicationPage'; + +/** + * The parameter list for the JobOffersNav navigator. + */ +export type JobOfferApplicationStackParamList = { + JobOffer: JobOfferPageParams; + JobOfferApplicationList: undefined; +}; + +const JobOfferApplicationStack = + createNativeStackNavigator(); + +/** + * The stack navigator for the job offers pages. + * @constructor + */ +const JobOffersApplicationNav = () => { + return ( + }} + > + + + + ); +}; + +export default JobOffersApplicationNav; diff --git a/front/src/pages/jobOffer/JobOfferNav.tsx b/front/src/pages/jobOffer/JobOfferNav.tsx index 724a1ec..48acf71 100644 --- a/front/src/pages/jobOffer/JobOfferNav.tsx +++ b/front/src/pages/jobOffer/JobOfferNav.tsx @@ -12,6 +12,7 @@ import JobOfferPage, { JobOfferPageParams } from './JobOfferPage'; export type JobOfferStackParamList = { JobOfferList: undefined; JobOffer: JobOfferPageParams; + JobOfferApplication: undefined; }; const JobOfferStack = createNativeStackNavigator(); diff --git a/front/src/pages/jobOffer/jobOfferApplicationPage.tsx b/front/src/pages/jobOffer/jobOfferApplicationPage.tsx new file mode 100644 index 0000000..e5569b1 --- /dev/null +++ b/front/src/pages/jobOffer/jobOfferApplicationPage.tsx @@ -0,0 +1,77 @@ +import { useFocusEffect } from '@react-navigation/native'; +import { NativeStackScreenProps } from '@react-navigation/native-stack'; +import { FC, useCallback } from 'react'; +import { ScrollView, StyleSheet } from 'react-native'; + +import JobOfferList from '@/components/jobOffers/JobOfferList'; +import { JobOffer } from '@/models/entities/jobOffer'; +import { useGetAppliedJobOffersQuery } from '@/store/api/jobOfferApiSlice'; + +import { JobOfferApplicationStackParamList } from './JobOfferApplicationNav'; + +/** + * The styles for the JobOfferApplicationPage component. + */ +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + contentContainer: { + gap: 8, + paddingBottom: 8, + paddingHorizontal: 16, + }, +}); + +/** + * The props for the JobOfferApplicationPage component. + */ +type JobOfferApplicationPageProps = NativeStackScreenProps< + JobOfferApplicationStackParamList, + 'JobOfferApplicationList' +>; + +/** + * Displays the page of job offers for the current user. + * @constructor + */ +const JobOfferApplicationPage: FC = ({ + navigation, +}) => { + // API calls + const { data: jobOffersApplied, refetch: refetchJobOffersApplied } = + useGetAppliedJobOffersQuery(); + + // Callbacks + const handleJobOfferPress = useCallback( + (jobOffer: JobOffer) => { + navigation.navigate('JobOffer', { id: jobOffer.id }); + }, + [navigation], + ); + + // Fetch data from the API when the page is focused + useFocusEffect( + useCallback(() => { + refetchJobOffersApplied(); + }, [refetchJobOffersApplied]), + ); + + if (jobOffersApplied === undefined) { + return null; + } + + return ( + + + + ); +}; + +export default JobOfferApplicationPage; diff --git a/front/src/pages/login/FirstLoginPage.tsx b/front/src/pages/login/FirstLoginPage.tsx index 7dc74d3..5af7d6d 100644 --- a/front/src/pages/login/FirstLoginPage.tsx +++ b/front/src/pages/login/FirstLoginPage.tsx @@ -69,7 +69,6 @@ const FirstLoginPage: FC = () => { putProfile(newProfile); }, [formData, putProfile]); - return ( `jobOffers/${id}`, providesTags: (_result, _error, id) => [{ type: 'JobOffer', id }], }), + getAppliedJobOffers: builder.query({ + query: () => { + return 'jobOffers?onlyApplied=true'; + }, + providesTags: (result) => + result + ? [ + ...result.map(({ id }) => ({ + type: 'JobOffer' as const, + id, + })), + { type: 'JobOffer', id: 'LIST' }, + ] + : [{ type: 'JobOffer', id: 'LIST' }], + }), postApplyJobOffer: builder.mutation({ query: (id) => ({ url: `jobOffers/${id}/apply`, @@ -37,4 +52,5 @@ export const { useGetJobOffersQuery, useGetJobOfferQuery, usePostApplyJobOfferMutation, + useGetAppliedJobOffersQuery, } = extendedApiSlice; From 101610270178d2e40acaae855b829458a623f5d5 Mon Sep 17 00:00:00 2001 From: Mauran Date: Fri, 9 Feb 2024 09:06:32 +0100 Subject: [PATCH 3/3] chore: fix lint Signed-off-by: Mauran --- .../com/linkedout/profile/function/profile/SetProfileOfUser.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt b/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt index 7167938..dee7b4d 100644 --- a/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt +++ b/backend/profile/src/main/kotlin/com/linkedout/profile/function/profile/SetProfileOfUser.kt @@ -16,7 +16,6 @@ import java.util.function.Function @Component class SetProfileOfUser(private val profileService: ProfileService) : Function { override fun apply(t: Request): Response = handleRequestError { - // Extract the request val request = t.setUserProfileRequest val userId = UUID.fromString(request.userId)