Skip to content

Commit 32ed97e

Browse files
authored
build: CI/CD 대상 브랜치를 dev → main 으로 변경
[build] CI/CD 대상 브랜치를 dev → main 으로 변경
2 parents 96b2514 + 06749c0 commit 32ed97e

50 files changed

Lines changed: 2326 additions & 1486 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"axios": "^1.9.0",
2525
"dayjs": "^1.11.13",
2626
"eslint-plugin-jsx-a11y": "^6.10.2",
27+
"event-source-polyfill": "^1.0.31",
2728
"notistack": "^3.0.2",
2829
"react": "^19.1.0",
2930
"react-dom": "^19.1.0",

src/api/company.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,30 @@ export function getCompanyNamesByType(companyType) {
1515
return api.get("/api/companies/names", {
1616
params: { companyType },
1717
});
18+
}
19+
20+
/**
21+
* 회사 이미지 업로드를 위한 presigned URL 발급
22+
* POST /api/companies/images/upload-url/issue
23+
*
24+
* @param {string} companyId - 회사 UUID
25+
* @param {string} fileName - 파일명
26+
* @returns {Promise<import("axios").AxiosResponse>} ApiResponse<CompanyImageUploadUrlResponse>
27+
*/
28+
export function getCompanyImageUploadUrl(companyId, fileName) {
29+
return api.post(`/api/companies/images/upload-url/issue`, {
30+
companyId,
31+
fileName,
32+
});
33+
}
34+
35+
/**
36+
* 회사 이미지 삭제
37+
* DELETE /api/companies/images/{companyId}
38+
*
39+
* @param {string} companyId - 회사 UUID
40+
* @returns {Promise<import("axios").AxiosResponse>} ApiResponse
41+
*/
42+
export function deleteCompanyImage(companyId) {
43+
return api.delete(`/api/companies/images/${companyId}`);
1844
}

src/api/notification.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ export const readNotification = (data) => api.put("/api/notifications", data);
1212

1313
export const getUnreadNotificationCount = () =>
1414
api.get("/api/notifications/unread-count");
15+
16+
const baseURL = import.meta.env.VITE_API_URL || "http://localhost:8080";
17+
18+
export const connectToNotificationStream = () =>
19+
`${baseURL}/api/real-notifications/connect`;

src/api/project.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,15 @@ export function deleteProject({ id }) {
6767
export function getProjectMembers(params) {
6868
return api.get("/api/projects/members", { params });
6969
}
70+
71+
/**
72+
* 프로젝트 상태 변경
73+
* @param {string} projectId - 프로젝트 UUID
74+
* @param {string} status - 변경할 상태(CONTRACT, IN_PROGRESS, PAYMENT, COMPLETED)
75+
* @returns {Promise<import("axios").AxiosResponse>} ApiResponse<ProjectStatusUpdateWebResponse>
76+
*/
77+
export function updateProjectStatus(projectId, status) {
78+
return api.post("/api/projects/project-status", null, {
79+
params: { projectId, status },
80+
});
81+
}

src/api/projectMember.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,13 @@ export function getProjectMemberList(companyId, projectId) {
6060
{ params: { companyId, projectId } }
6161
);
6262
}
63+
64+
/**
65+
* 프로젝트 매니저 임명/해임
66+
* PUT /api/project-member/manager
67+
* @param {{ memberId: string, projectId: string }} data
68+
* @returns {Promise<import("axios").AxiosResponse>} ApiResponse<ProjectManagerUpdateWebResponse>
69+
*/
70+
export function updateProjectManager(data) {
71+
return api.put("/api/project-member/update-project-manager", data);
72+
}

src/components/common/customTable/CustomTable.jsx

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -211,40 +211,66 @@ export default function CustomTable({
211211
</TableHead>
212212

213213
<TableBody>
214-
{rows.map((row, idx) => (
215-
<TableRow
216-
key={idx}
217-
hover
218-
onClick={() => onRowClick?.(row)}
219-
sx={{ cursor: "pointer" }}
220-
>
221-
{columns.map((col) => (
222-
<TableCell key={col.key}>
223-
{renderCell(col, row[col.key], row, theme, companies)}
224-
</TableCell>
225-
))}
226-
{userRole === "ROLE_SYSTEM_ADMIN" &&
227-
!hideDeleteButton &&
228-
!row.deleted && (
229-
<TableCell key="__actions__" align="center">
230-
<CustomButton
231-
kind="ghost-danger"
232-
size="small"
233-
onClick={(e) => {
234-
e.stopPropagation();
235-
onDelete?.(row);
236-
}}
237-
>
238-
삭제
239-
</CustomButton>
214+
{rows.length > 0 ? (
215+
rows.map((row, idx) => (
216+
<TableRow
217+
key={idx}
218+
hover
219+
onClick={() => onRowClick?.(row)}
220+
sx={{ cursor: "pointer" }}
221+
>
222+
{columns.map((col) => (
223+
<TableCell key={col.key}>
224+
{renderCell(col, row[col.key], row, theme, companies)}
240225
</TableCell>
241-
)}
226+
))}
227+
{userRole === "ROLE_SYSTEM_ADMIN" &&
228+
!hideDeleteButton &&
229+
!row.deleted && (
230+
<TableCell key="__actions__" align="center">
231+
<CustomButton
232+
kind="ghost-danger"
233+
size="small"
234+
onClick={(e) => {
235+
e.stopPropagation();
236+
onDelete?.(row);
237+
}}
238+
>
239+
삭제
240+
</CustomButton>
241+
</TableCell>
242+
)}
243+
</TableRow>
244+
))
245+
) : (
246+
<TableRow>
247+
<TableCell
248+
colSpan={fullColumns.length}
249+
sx={{
250+
height: 200,
251+
p: 0,
252+
}}
253+
>
254+
<Box
255+
sx={{
256+
display: "flex",
257+
justifyContent: "center",
258+
alignItems: "center",
259+
height: "100%",
260+
width: "100%",
261+
}}
262+
>
263+
<Typography variant="body2" color="text.secondary">
264+
등록된 데이터가 없습니다.
265+
</Typography>
266+
</Box>
267+
</TableCell>
242268
</TableRow>
243-
))}
269+
)}
244270
</TableBody>
245271
</Table>
246272

247-
{pagination && (
273+
{pagination && rows.length > 0 && (
248274
<Box p={2}>
249275
<Stack direction="row" justifyContent="flex-end">
250276
<Pagination

src/features/auth/authSlice.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,19 @@ export const reissueToken = createAsyncThunk(
2626
}
2727
);
2828

29-
export const logout = createAsyncThunk(
30-
"auth/logout",
31-
async (_, thunkAPI) => {
32-
try {
33-
await authAPI.logout();
34-
return true;
35-
} catch (error) {
36-
return thunkAPI.rejectWithValue(error.response?.data || "Logout failed");
37-
}
29+
export const logout = createAsyncThunk("auth/logout", async (_, thunkAPI) => {
30+
try {
31+
await authAPI.logout();
32+
return true;
33+
} catch (error) {
34+
return thunkAPI.rejectWithValue(error.response?.data || "Logout failed");
3835
}
39-
);
36+
});
4037

41-
const storedToken = localStorage.getItem("accessToken");
38+
const storedToken = localStorage.getItem("accessToken");
4239
const storedUserJson = localStorage.getItem("user");
4340
const storedCompanyJson = localStorage.getItem("company");
44-
const initialUser = storedUserJson ? JSON.parse(storedUserJson) : null;
41+
const initialUser = storedUserJson ? JSON.parse(storedUserJson) : null;
4542
const initialCompany = storedCompanyJson ? JSON.parse(storedCompanyJson) : null;
4643

4744
const authSlice = createSlice({
@@ -178,3 +175,5 @@ const authSlice = createSlice({
178175

179176
export const { clearAuthState } = authSlice.actions;
180177
export default authSlice.reducer;
178+
export const getAccessToken = (state) => state.auth.accessToken;
179+
export const getUser = (state) => state.auth.user;

src/features/company/components/CompanyForm.jsx

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ import {
1111
MenuItem,
1212
} from "@mui/material";
1313
import { InfoOutlined } from "@mui/icons-material";
14+
import CompanyImageUploadSection from "./CompanyImageUploadSection";
1415

1516
export default function CompanyForm({
1617
form,
1718
handleChange,
1819
isSubmitted = false,
20+
imageUploadProps,
1921
}) {
2022
return (
2123
<Box
@@ -162,25 +164,7 @@ export default function CompanyForm({
162164
</Box>
163165

164166
{/* 4) 로고 이미지 */}
165-
{/* <Box>
166-
<Stack direction="row" alignItems="center" spacing={1}>
167-
<Typography variant="subtitle1" fontWeight={600}>
168-
4. 로고 이미지
169-
</Typography>
170-
<Tooltip title="회사 로고 이미지 경로를 입력하세요.">
171-
<InfoOutlined fontSize="small" color="action" />
172-
</Tooltip>
173-
</Stack>
174-
<Divider sx={{ mt: 1, mb: 2 }} />
175-
176-
<TextField
177-
label="로고 이미지 경로"
178-
placeholder="/images/company-logo.png"
179-
value={form.logoImagePath || ""}
180-
onChange={handleChange("logoImagePath")}
181-
fullWidth
182-
/>
183-
</Box> */}
167+
<CompanyImageUploadSection {...imageUploadProps} />
184168
</Stack>
185169
</Paper>
186170
</Box>

0 commit comments

Comments
 (0)