GitHub - fc-micro-frontends/career-up at step17
REACT_APP_AUTH0_DOMAIN=dev-vcrmf0xuep020tri.us.auth0.com
REACT_APP_AUTH0_CLIENT_ID=27LLb4I9cIjiiQNSjbNIX9sQM1KECUfk
REACT_APP_AUTH0_CALLBACK_URL=http://localhost:3000
➜ pnpm i
➜ pnpm build
// career-up/apps/job/webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const Dotenv = require("dotenv-webpack");
const deps = require("./package.json").dependencies;
module.exports = (_, argv) => ({
output: {
publicPath: "<http://localhost:3004/>",
},
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
},
devServer: {
port: 3004,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\\.m?js/,
type: "javascript/auto",
resolve: {
fullySpecified: false,
},
},
{
test: /\\.(css|s[ac]ss)$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
{
test: /\\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
plugins: [
new Dotenv({
path: "../../.env",
}),
new ModuleFederationPlugin({
name: "job",
filename: "remoteEntry.js",
remotes: {},
exposes: {
"./injector": "./src/injector.tsx",
**"./fragment-recommend-jobs":
"./src/fragments/recommend-jobs-container.tsx",**
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
"@career-up/shell-router": {
singleton: true,
},
"@career-up/ui-kit": {
singleton: true,
},
},
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
}),
],
});
// career-up/apps/job/src/fragments/recommend-jobs-container.tsx
import React, { useCallback, useState } from "react";
import RecommendJobs from "../components/recommend-jobs";
import { type JobType } from "../types";
import { useAuth0Client } from "@career-up/shell-router";
import { getJobs } from "../apis";
const RecommendJobsContainer: React.FC = () => {
const auth0Client = useAuth0Client();
const [jobs, setJobs] = useState<JobType[]>([]);
const fetchJobs = useCallback(async () => {
try {
const token = await auth0Client.getTokenSilently();
const jobs = await getJobs(token);
setJobs(jobs.slice(0, 3));
} catch (error) {
alert(error);
}
}, [auth0Client]);
return <RecommendJobs jobs={jobs} fetchJobs={fetchJobs} />;
};
export default RecommendJobsContainer;
// career-up/apps/job/src/components/recommend-jobs.styles.ts
import styled from "@emotion/styled";
export const RecommendJobsWrapper = styled.div`
.job--recommend-jobs-top {
display: flex;
flex-direction: column;
background-color: white;
padding: 16px 12px 16px;
border-radius: 8px 8px 0 0;
border-bottom: 1px solid rgb(0 0 0 / 0.1);
gap: 10px;
}
.job--recommend-jobs-top-title {
font-size: 15px;
font-weight: bold;
height: 15px;
}
.job--recommend-jobs-bottom {
display: flex;
flex-direction: column;
border-radius: 0 0 8px 8px;
background-color: white;
}
`;
// career-up/apps/job/src/components/recommend-jobs.tsx
import React, { useEffect } from "react";
import { RecommendJobsWrapper } from "./recommend-jobs.styles";
import { JobType } from "../types";
import RecommendJob from "./recommend-job";
interface RecommendJobsProps {
jobs: JobType[];
fetchJobs: () => Promise<void>;
}
const RecommendJobs: React.FC<RecommendJobsProps> = ({ jobs, fetchJobs }) => {
useEffect(() => {
fetchJobs();
}, [fetchJobs]);
return (
<RecommendJobsWrapper>
<div className="job--recommend-jobs-top">
<span className="job--recommend-jobs-top-title">추천 채용공고</span>
</div>
<div className="job--recommend-jobs-bottom">
{jobs.map((job) => (
<RecommendJob key={job.id} {...job} />
))}
</div>
</RecommendJobsWrapper>
);
};
export default RecommendJobs;
// career-up/apps/job/src/components/recommend-job.styles.ts
import styled from "@emotion/styled";
export const RecommendJobWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 16px 12px 16px;
.job--recommend-job-position {
font-size: 16px;
font-weight: 600;
color: rgb(0 0 0 / 0.9);
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
.job--recommend-job-company {
font-size: 14px;
color: rgb(0 0 0 / 0.6);
}
:hover {
background-color: rgb(0 0 0 / 0.1);
cursor: pointer;
}
`;
// career-up/apps/job/src/components/recommend-job.tsx
import "./recommend-job.styles";
import React from "react";
import { RecommendJobWrapper } from "./recommend-job.styles";
import { useShellNavigate } from "@career-up/shell-router";
interface RecommendJobProps {
id: number;
position: string;
company: string;
}
const RecommendJob: React.FC<RecommendJobProps> = ({
id,
position,
company,
}) => {
const navigate = useShellNavigate();
const onClick = () => {
navigate(`/job/${id}`);
};
return (
<RecommendJobWrapper onClick={onClick}>
<div className="job--recommend-job-position">{position}</div>
<div className="job--recommend-job-company">{company}</div>
</RecommendJobWrapper>
);
};
export default RecommendJob;
➜ pnpm dev