하이어+플러스! 직원용 빌드 방법은 다음과 같습니다(UI - 작업).

개요: 작업과 관련된 모든 보기 및 기능, 호출된 모든 기능은 jobReducer에서 가져옵니다.




작업 경로 페이지



인사이드routes > job > job-page.tsx렌더링할 구성 요소와 호출할 함수를 지원하는 가져오기. 마운트 시 모든 작업을 가져옵니다. searchInputfilteredData 를 사용하여 검색 및 필터 상태를 처리하고 있습니다.
searchItems - 검색어로 작업을 필터링하고 결과를 filteredData로 설정합니다. 아무것도 검색되지 않으면 filteredData가 기본값jobs으로 설정됩니다.

import { useEffect, useState } from 'react';
import BeatLoader from 'react-spinners/BeatLoader';
import { getPostedJobs } from '../../app/features/job/jobSlice';
import { JobData } from '../../app/features/job/jobTypes';
import { useAppDispatch, useAppSelector } from '../../app/hooks';
import Job from '../../components/job/job.component';

const JobsPage = () => {
    const dispatch = useAppDispatch();
    const { jobs, isLoading } = useAppSelector((state) => state.job);

    const [searchInput, setSearchInput] = useState<string>('');
    const [filteredData, setfilteredData] = useState<JobData[]>([]);

    useEffect(() => {
        dispatch(getPostedJobs());
    }, []);

    const searchItems = (value: string) => {
        setSearchInput(value);
        if (searchInput !== '') {
            const filtered = jobs.filter((item) => {
                return Object.values(item)
                    .join('')
                    .toLowerCase()
                    .includes(searchInput.toLowerCase());
            });
            setfilteredData(filtered);
        } else {
            setfilteredData(jobs);
        }
    };
    return ({/* removed for simplicity */});
};

export default JobsPage;



UI



간단히 말해서 검색 표시줄로 모든 작업을 렌더링합니다. 직책 및/또는 위치로 검색하면 작업 구성 요소에 필터링된 결과가 표시됩니다.

const JobsPage = () => {
{/* removed for simplicity */}
    return (
        <>
            {isLoading ? (
                <div className="text-center p-20">
                    <BeatLoader color="#ffffff" />
                </div>
            ) : (
                <>
                    <div className="flex justify-center pt-20">
                        <div className="mb-3 w-1/2">
                            <div className="input-group relative flex items-stretch w-full mb-4">
                                <input
                                    value={searchInput}
                                    onChange={(e) => searchItems(e.target.value)}
                                    type="search"
                                    className="form-control relative flex-auto min-w-0 block w-full px-5 py-3 text-base font-normal font-color secondary-bg-color bg-clip-padding border border-solid border-gray-300 rounded-full transition ease-in-out m-0 focus:text-slate-200 focus:secondary-bg-color focus:border-indigo-700 focus:outline-none"
                                    placeholder="Search for a job..."
                                    aria-label="Search"
                                    aria-describedby="button-addon2"
                                />
                            </div>
                        </div>
                    </div>
                    <section className="text-gray-600 body-font overflow-hidden">
                        <div className="container px-5 py-24 mx-auto">
                            <div className="-my-8 divide-y-2 divide-gray-700">
                                {searchInput.length
                                    ? filteredData.map((job, index) => {
                                            return <Job job={job} key={index} />;
                                      })
                                    : jobs.map((job, index) => {
                                            return <Job job={job} key={index} />;
                                      })}
                            </div>
                        </div>
                    </section>
                </>
            )}
        </>
    );
};

export default JobsPage;



스크린샷


  • 필터링되지 않은 경우
  • 필터링된 경우





  • 인사이드routes > job > job-detail.tsx호출할 함수를 지원하는 가져오기. 마운트 시 id 로 단일 작업을 가져옵니다. useParams 에서 가져옵니다. 결과를 구문 분석하고 로컬 상태jobData로 설정합니다.

    import { useEffect, useState } from 'react';
    import { useParams } from 'react-router';
    import BeatLoader from 'react-spinners/BeatLoader';
    import { getPostedJobById } from '../../app/features/job/jobSlice';
    import { JobData } from '../../app/features/job/jobTypes';
    import { useAppDispatch, useAppSelector } from '../../app/hooks';
    
    const JobDetail = () => {
        const { id } = useParams();
        const [jobData, setjobData] = useState<JobData>({} as JobData);
        const { isLoading } = useAppSelector((state) => state.job);
        const dispatch = useAppDispatch();
    
        useEffect(() => {
            dispatch(getPostedJobById(id))
                .unwrap()
                .then((val) => {
                    setjobData(JSON.parse(val));
                });
        }, [dispatch, id]);
    
        return ( {/* removed for simplicity */} );
    };
    
    export default JobDetail;
    
    


    UI



    간단히 말해서 작업의 세부 정보를 렌더링합니다.

    const JobDetail = () => {
        {/* removed for simplicity */}
        return (
            <>
                {isLoading ? (
                    <BeatLoader />
                ) : (
                    <>
                        <section style={{ backgroundColor: '#252731' }}>
                            <div className="md:px-12 lg:px-24 max-w-7xl relative items-center w-full px-5 py-20 mx-auto">
                                <div className="mx-auto flex flex-col w-full max-w-lg text-center">
                                    <p className="mb-5 font-medium text-3xl text-white">
                                        {jobData.position}
                                    </p>
                                    <div>
                                        <span className="font-color">
                                            {jobData.location} - {jobData.salary}
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </section>
                        <section>
                            <div className="divide-y divide-gray-700">
                                <section className="text-gray-600 body-font mt-2">
                                    <div className="container px-5 py-20 mx-auto">
                                        <div className="flex flex-col w-full mx-auto">
                                            <div className="w-full mx-auto">
                                                <h2 className="xs:text-3xl text-2xl my-5 font-bold">
                                                    Job Description
                                                </h2>
                                                <div>
                                                    <p className="font-color">{jobData.description}</p>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </section>
                                <section className="text-gray-600 body-font mt-2">
                                    <div className="container px-5 py-20 mx-auto">
                                        <div className="flex flex-col w-full mx-auto">
                                            <div className="w-full mx-auto">
                                                <h2 className="xs:text-3xl text-2xl my-5 font-bold">
                                                    Job-Type
                                                </h2>
                                                <div>
                                                    <p className="font-color">{jobData.jobType}</p>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </section>
                            </div>
                        </section>
                    </>
                )}
            </>
        );
    };
    
    export default JobDetail;
    
    


    스크린샷






    작업 구성 요소



    인사이드components > job > job.component.tsx너무 긴 텍스트에 대한 도우미 함수truncateString를 만들었습니다. 텍스트가 최대 길이에 도달하면 표시됨...
    소품에서 작업 데이터를 얻습니다. typescript를 사용하고 있기 때문에 소품의 데이터 유형이 무엇인지 정의했습니다. 제 경우에는 JobData 입니다.

    import React from 'react';
    import { Link } from 'react-router-dom';
    import { JobData } from '../../app/features/job/jobTypes';
    import { truncateString } from '../../utils/truncateString';
    
    interface JobProps {
         job: JobData;
    }
    


    UI



    세부 정보를 보고, 작업에 지원하고, 게시한 회사를 볼 수 있는 링크가 있는 작업 카드.

    const Job: React.FC<JobProps> = ({ job }) => {
        return (
            <div className="py-8 flex flex-wrap md:flex-nowrap">
                <div className="md:w-64 md:mb-0 mb-6 flex-shrink-0 flex flex-col">
                    <span className="font-semibold title-font text-indigo-500">
                        {job.companyName.toUpperCase()}
                    </span>
                    <span className="mt-1 font-color text-sm">{job.datePosted}</span>
                </div>
                <div className="md:flex-grow">
                    <h2 className="text-2xl font-medium text-white title-font mb-2">
                        {job.position}{' '}
                        <span className="text-indigo-500 text-sm">
                            ({job.location}) - ({job.jobType})
                        </span>
                    </h2>
                    <p className="leading-relaxed font-color max-w-3xl">
                        {truncateString(job.description, 250)}
                    </p>
                    <a
                        href={job.applyUrl}
                        className="text-indigo-500 inline-flex items-center mt-4 mr-4"
                    >
                        APPLY NOW
                        <svg
                            className="w-4 h-4 ml-2"
                            viewBox="0 0 24 24"
                            stroke="currentColor"
                            strokeWidth="2"
                            fill="none"
                            strokeLinecap="round"
                            strokeLinejoin="round"
                        >
                            <path d="M5 12h14"></path>
                            <path d="M12 5l7 7-7 7"></path>
                        </svg>
                    </a>
                    <Link
                        to={`job/${job.id}`}
                        className="text-indigo-500 inline-flex items-center mt-4 mr-3"
                    >
                        VIEW JOB
                        <svg
                            className="w-4 h-4 ml-2"
                            viewBox="0 0 24 24"
                            stroke="currentColor"
                            strokeWidth="2"
                            fill="none"
                            strokeLinecap="round"
                            strokeLinejoin="round"
                        >
                            <path d="M5 12h14"></path>
                            <path d="M12 5l7 7-7 7"></path>
                        </svg>
                    </Link>
                    <Link
                        to={`company/${job.id}`}
                        className="text-indigo-500 inline-flex items-center mt-4"
                    >
                        VIEW COMPANY
                        <svg
                            className="w-4 h-4 ml-2"
                            viewBox="0 0 24 24"
                            stroke="currentColor"
                            strokeWidth="2"
                            fill="none"
                            strokeLinecap="round"
                            strokeLinejoin="round"
                        >
                            <path d="M5 12h14"></path>
                            <path d="M12 5l7 7-7 7"></path>
                        </svg>
                    </Link>
                </div>
            </div>
        );
    };
    
    export default Job;
    
    


    프로젝트의 UI/작업 부분은 여기까지입니다. 계속 지켜봐 주세요!

    좋은 웹페이지 즐겨찾기