first commit

This commit is contained in:
2026-03-25 21:00:01 +00:00
commit 6db103cd04
6 changed files with 359 additions and 0 deletions

7
Awesome_API/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"java.project.sourcePaths": ["src"],
"java.project.outputPath": "bin",
"java.project.referencedLibraries": [
"lib/**/*.jar"
]
}

18
Awesome_API/README.md Normal file
View File

@@ -0,0 +1,18 @@
## Getting Started
Welcome to the VS Code Java world. Here is a guideline to help you get started to write Java code in Visual Studio Code.
## Folder Structure
The workspace contains two folders by default, where:
- `src`: the folder to maintain sources
- `lib`: the folder to maintain dependencies
Meanwhile, the compiled output files will be generated in the `bin` folder by default.
> If you want to customize the folder structure, open `.vscode/settings.json` and update the related settings there.
## Dependency Management
The `JAVA PROJECTS` view allows you to manage your dependencies. More details can be found [here](https://github.com/microsoft/vscode-java-dependency#manage-dependencies).

Binary file not shown.

Binary file not shown.

BIN
Awesome_API/bin/Main.class Normal file

Binary file not shown.

334
Awesome_API/src/Main.java Normal file
View File

@@ -0,0 +1,334 @@
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class Main extends JFrame {
// Cores do Design Moderno
private static final Color COLOR_BG_TOP = new Color(138, 180, 248);
private static final Color COLOR_BG_BOTTOM = new Color(25, 103, 210);
private static final Color COLOR_CARD = new Color(255, 255, 255, 220);
private static final Color COLOR_BTN_PRIMARY = new Color(242, 186, 45);
private static final Color COLOR_BTN_SECONDARY = new Color(219, 68, 55);
// Dados limpos
private String[] moedaDisplay = {
"Dólar Americano (USD)", "Euro (EUR)", "Real Brasileiro (BRL)",
"Libra Esterlina (GBP)", "Iene Japonês (JPY)", "Dólar Canadense (CAD)",
"Dólar Australiano (AUD)", "Franco Suíço (CHF)"
};
private String[] moedaAbrev = {"USD", "EUR", "BRL", "GBP", "JPY", "CAD", "AUD", "CHF"};
private JComboBox<String> cmbFrom;
private JComboBox<String> cmbTo;
private JTextField txtValue;
private JLabel lblResult;
private JLabel lblResultSub;
// Texto de Exemplo (Placeholder)
private final String PLACEHOLDER_TEXT = "Ex: 100.00";
public Main() {
setTitle("Conversor de Moedas");
setSize(420, 750);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// Painel Principal com Gradiente Azul
JPanel mainPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0, COLOR_BG_TOP, 0, getHeight(), COLOR_BG_BOTTOM);
g2.setPaint(gp);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
}
};
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(new EmptyBorder(20, 20, 20, 20));
setContentPane(mainPanel);
// --- TÍTULO ---
JLabel title = new JLabel("Conversor de Moedas", SwingConstants.CENTER);
title.setFont(new Font("Segoe UI", Font.BOLD, 30));
title.setForeground(Color.WHITE);
title.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(title);
mainPanel.add(Box.createVerticalStrut(20));
// --- CARTÃO 1: SELEÇÃO DE MOEDAS ---
RoundedPanel cardMoedas = new RoundedPanel();
cardMoedas.setLayout(new BoxLayout(cardMoedas, BoxLayout.Y_AXIS));
JLabel lblDe = new JLabel("Converter De:");
lblDe.setFont(new Font("Segoe UI", Font.PLAIN, 14));
lblDe.setForeground(Color.DARK_GRAY);
cmbFrom = new JComboBox<>(moedaDisplay);
styleComboBox(cmbFrom);
JLabel lblPara = new JLabel("Para:");
lblPara.setFont(new Font("Segoe UI", Font.PLAIN, 14));
lblPara.setForeground(Color.DARK_GRAY);
cmbTo = new JComboBox<>(moedaDisplay);
styleComboBox(cmbTo);
cmbTo.setSelectedIndex(2); // Padrão BRL
JPanel pnlDe = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlDe.setOpaque(false); pnlDe.add(lblDe);
JPanel pnlPara = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlPara.setOpaque(false); pnlPara.add(lblPara);
cardMoedas.add(pnlDe);
cardMoedas.add(cmbFrom);
cardMoedas.add(Box.createVerticalStrut(15));
cardMoedas.add(pnlPara);
cardMoedas.add(cmbTo);
mainPanel.add(cardMoedas);
mainPanel.add(Box.createVerticalStrut(15));
// --- CARTÃO 2: QUANTIDADE COM PLACEHOLDER ---
RoundedPanel cardValor = new RoundedPanel();
cardValor.setLayout(new BoxLayout(cardValor, BoxLayout.Y_AXIS));
JLabel lblVal = new JLabel("Quantidade a Converter:");
lblVal.setFont(new Font("Segoe UI", Font.PLAIN, 14));
lblVal.setForeground(Color.DARK_GRAY);
JPanel pnlVal = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlVal.setOpaque(false); pnlVal.add(lblVal);
// Configuração do Placeholder
txtValue = new JTextField(PLACEHOLDER_TEXT);
txtValue.setForeground(Color.GRAY); // Cor de texto fantasma
styleTextField(txtValue);
// Evento para limpar o placeholder quando se clica
txtValue.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
if (txtValue.getText().equals(PLACEHOLDER_TEXT)) {
txtValue.setText("");
txtValue.setForeground(Color.BLACK); // Volta à cor normal para o user escrever
}
}
@Override
public void focusLost(FocusEvent e) {
if (txtValue.getText().isEmpty()) {
txtValue.setForeground(Color.GRAY);
txtValue.setText(PLACEHOLDER_TEXT); // Volta o texto fantasma se não escreverem nada
}
}
});
cardValor.add(pnlVal);
cardValor.add(txtValue);
mainPanel.add(cardValor);
mainPanel.add(Box.createVerticalStrut(20));
// --- BOTÕES PRINCIPAIS ---
JButton btnConvert = new RoundedButton("Converter Agora", COLOR_BTN_PRIMARY, Color.BLACK);
mainPanel.add(btnConvert);
mainPanel.add(Box.createVerticalStrut(10));
JButton btnInvert = new RoundedButton("🔁 Inverter Moedas", COLOR_BTN_SECONDARY, Color.WHITE);
btnInvert.addActionListener(e -> inverterMoedas());
mainPanel.add(btnInvert);
mainPanel.add(Box.createVerticalStrut(20));
// --- CARTÃO 3: RESULTADO ---
RoundedPanel cardResult = new RoundedPanel();
cardResult.setLayout(new BoxLayout(cardResult, BoxLayout.Y_AXIS));
JLabel lblRecebera = new JLabel("Você receberá:");
lblRecebera.setFont(new Font("Segoe UI", Font.PLAIN, 14));
lblRecebera.setForeground(Color.DARK_GRAY);
lblRecebera.setAlignmentX(Component.CENTER_ALIGNMENT);
lblResult = new JLabel("0.00", SwingConstants.CENTER);
lblResult.setFont(new Font("Segoe UI", Font.BOLD, 42));
lblResult.setForeground(new Color(20, 20, 20));
lblResult.setAlignmentX(Component.CENTER_ALIGNMENT);
lblResultSub = new JLabel("-");
lblResultSub.setFont(new Font("Segoe UI", Font.PLAIN, 16));
lblResultSub.setForeground(Color.DARK_GRAY);
lblResultSub.setAlignmentX(Component.CENTER_ALIGNMENT);
cardResult.add(Box.createVerticalStrut(10));
cardResult.add(lblRecebera);
cardResult.add(Box.createVerticalStrut(10));
cardResult.add(lblResult);
cardResult.add(lblResultSub);
cardResult.add(Box.createVerticalStrut(10));
mainPanel.add(cardResult);
// --- LÓGICA DO BOTÃO CONVERTER ---
btnConvert.addActionListener(e -> {
int indexFrom = cmbFrom.getSelectedIndex();
int indexTo = cmbTo.getSelectedIndex();
String input = txtValue.getText().replace(",", ".");
// Verifica se o utilizador não escreveu nada e deixou o placeholder lá
if (input.equals(PLACEHOLDER_TEXT) || input.isEmpty()) {
JOptionPane.showMessageDialog(this, "Insere um número válido, senão vai dar merda!", "Erro", JOptionPane.ERROR_MESSAGE);
return;
}
final double val;
try {
val = Double.parseDouble(input);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "Apenas números, por favor. Senão vai dar merda!", "Erro", JOptionPane.ERROR_MESSAGE);
return;
}
if (indexFrom == indexTo) {
lblResult.setText(String.format("%.2f %s", val, moedaAbrev[indexTo]));
lblResultSub.setText(moedaDisplay[indexTo]);
return;
}
lblResult.setText("A calcular...");
new Thread(() -> {
try {
String m1 = moedaAbrev[indexFrom];
String m2 = moedaAbrev[indexTo];
double rate = obterTaxaDeCambio(m1, m2);
double finalValue = val * rate;
SwingUtilities.invokeLater(() -> {
lblResult.setText(String.format("%.2f %s", finalValue, m2));
lblResultSub.setText(moedaDisplay[indexTo]);
});
} catch (Exception ex) {
SwingUtilities.invokeLater(() -> {
lblResult.setText("Erro");
JOptionPane.showMessageDialog(this, "Erro de rede: " + ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
});
}
}).start();
});
// Foca o ecrã para o placeholder funcionar logo na primeira vez
getContentPane().requestFocusInWindow();
}
private void inverterMoedas() {
int indexFrom = cmbFrom.getSelectedIndex();
int indexTo = cmbTo.getSelectedIndex();
cmbFrom.setSelectedIndex(indexTo);
cmbTo.setSelectedIndex(indexFrom);
}
private static double obterTaxaDeCambio(String m1, String m2) throws Exception {
String urlStr = "https://economia.awesomeapi.com.br/json/last/" + m1 + "-" + m2;
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
if (conn.getResponseCode() != 200) throw new IOException("HTTP Error: " + conn.getResponseCode());
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) response.append(line);
reader.close();
Pattern pattern = Pattern.compile("\"bid\"\\s*:\\s*\"([^\"]+)\"");
Matcher matcher = pattern.matcher(response.toString());
if (matcher.find()) return Double.parseDouble(matcher.group(1));
else throw new Exception("Chave 'bid' não encontrada.");
}
// --- CLASSES DE ESTILO CUSTOMIZADAS ---
// Painel Arredondado
class RoundedPanel extends JPanel {
public RoundedPanel() {
setOpaque(false);
setBorder(new EmptyBorder(15, 20, 15, 20));
setMaximumSize(new Dimension(360, 200));
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(0, 0, 0, 20));
g2.fillRoundRect(2, 2, getWidth() - 4, getHeight() - 4, 25, 25);
g2.setColor(COLOR_CARD);
g2.fillRoundRect(0, 0, getWidth() - 4, getHeight() - 4, 25, 25);
g2.dispose();
super.paintComponent(g);
}
}
// Botão Arredondado
class RoundedButton extends JButton {
private Color bgColor;
public RoundedButton(String text, Color bg, Color fg) {
super(text);
this.bgColor = bg;
setForeground(fg);
setFont(new Font("Segoe UI", Font.BOLD, 18));
setFocusPainted(false);
setContentAreaFilled(false);
setBorderPainted(false);
setAlignmentX(Component.CENTER_ALIGNMENT);
setMaximumSize(new Dimension(360, 50));
setCursor(new Cursor(Cursor.HAND_CURSOR));
addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) { bgColor = bg.brighter(); repaint(); }
public void mouseExited(MouseEvent e) { bgColor = bg; repaint(); }
});
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(0, 0, 0, 30));
g2.fillRoundRect(2, 4, getWidth() - 4, getHeight() - 4, 20, 20);
g2.setColor(bgColor);
g2.fillRoundRect(0, 0, getWidth() - 4, getHeight() - 5, 20, 20);
g2.dispose();
super.paintComponent(g);
}
}
private void styleComboBox(JComboBox<String> cb) {
cb.setMaximumSize(new Dimension(320, 40));
cb.setFont(new Font("Segoe UI", Font.PLAIN, 16));
cb.setBackground(Color.WHITE);
cb.setFocusable(false);
cb.setAlignmentX(Component.CENTER_ALIGNMENT);
}
private void styleTextField(JTextField tf) {
tf.setMaximumSize(new Dimension(320, 45));
tf.setFont(new Font("Segoe UI", Font.PLAIN, 18));
tf.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1, true),
new EmptyBorder(5, 10, 5, 10)
));
tf.setAlignmentX(Component.CENTER_ALIGNMENT);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Main().setVisible(true);
});
}
}